From c68dda815e64fb2fb463318d1eaa304e22199d50 Mon Sep 17 00:00:00 2001 From: Preston Gurd Date: Thu, 12 Apr 2012 20:13:57 +0000 Subject: [PATCH] This patch improves the MCJIT runtime dynamic loader by adding new handling of zero-initialized sections, virtual sections and common symbols and preventing the loading of sections which are not required for execution such as debug information. Patch by Andy Kaylor! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@154610 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/COFF.h | 4 + include/llvm/Object/ELF.h | 50 +++++ include/llvm/Object/MachO.h | 4 + include/llvm/Object/ObjectFile.h | 28 +++ lib/ExecutionEngine/MCJIT/MCJIT.cpp | 6 +- lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp | 203 +++++++++++++++------ lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp | 3 +- lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h | 9 + lib/Object/COFFObjectFile.cpp | 21 +++ lib/Object/MachOObjectFile.cpp | 55 +++++- test/ExecutionEngine/2002-12-16-ArgTest.ll | 1 - test/ExecutionEngine/2003-01-04-ArgumentBug.ll | 1 - test/ExecutionEngine/2003-01-04-LoopTest.ll | 1 - test/ExecutionEngine/2003-05-06-LivenessClobber.ll | 1 - test/ExecutionEngine/2003-05-07-ArgumentTest.ll | 1 - test/ExecutionEngine/2003-08-21-EnvironmentTest.ll | 1 - test/ExecutionEngine/2005-12-02-TailCallBug.ll | 1 - test/ExecutionEngine/hello.ll | 1 - test/ExecutionEngine/hello2.ll | 1 - test/ExecutionEngine/stubs.ll | 1 - .../ExecutionEngine/test-call-no-external-funcs.ll | 1 - test/ExecutionEngine/test-call.ll | 1 - test/ExecutionEngine/test-common-symbols.ll | 1 - test/ExecutionEngine/test-fp-no-external-funcs.ll | 1 - test/ExecutionEngine/test-fp.ll | 1 - test/ExecutionEngine/test-global-init-nonzero.ll | 1 - test/ExecutionEngine/test-global.ll | 1 - test/ExecutionEngine/test-loadstore.ll | 1 - 28 files changed, 320 insertions(+), 81 deletions(-) diff --git a/include/llvm/Object/COFF.h b/include/llvm/Object/COFF.h index 91971bb01bb..68b5ca1bc78 100644 --- a/include/llvm/Object/COFF.h +++ b/include/llvm/Object/COFF.h @@ -126,6 +126,10 @@ protected: virtual error_code isSectionText(DataRefImpl Sec, bool &Res) const; virtual error_code isSectionData(DataRefImpl Sec, bool &Res) const; virtual error_code isSectionBSS(DataRefImpl Sec, bool &Res) const; + virtual error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const; + virtual error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const; + virtual error_code isSectionRequiredForExecution(DataRefImpl Sec, + bool &Res) const; virtual error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, bool &Result) const; virtual relocation_iterator getSectionRelBegin(DataRefImpl Sec) const; diff --git a/include/llvm/Object/ELF.h b/include/llvm/Object/ELF.h index cb013b9414b..455a67b49f4 100644 --- a/include/llvm/Object/ELF.h +++ b/include/llvm/Object/ELF.h @@ -33,6 +33,15 @@ namespace llvm { namespace object { +// Subclasses of ELFObjectFile may need this for template instantiation +inline std::pair +getElfArchType(MemoryBuffer *Object) { + if (Object->getBufferSize() < ELF::EI_NIDENT) + return std::make_pair((uint8_t)ELF::ELFCLASSNONE,(uint8_t)ELF::ELFDATANONE); + return std::make_pair( (uint8_t)Object->getBufferStart()[ELF::EI_CLASS] + , (uint8_t)Object->getBufferStart()[ELF::EI_DATA]); +} + // Templates to choose Elf_Addr and Elf_Off depending on is64Bits. template struct ELFDataTypeTypedefHelperCommon { @@ -540,6 +549,10 @@ protected: virtual error_code isSectionText(DataRefImpl Sec, bool &Res) const; virtual error_code isSectionData(DataRefImpl Sec, bool &Res) const; virtual error_code isSectionBSS(DataRefImpl Sec, bool &Res) const; + virtual error_code isSectionRequiredForExecution(DataRefImpl Sec, + bool &Res) const; + virtual error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const; + virtual error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const; virtual error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, bool &Result) const; virtual relocation_iterator getSectionRelBegin(DataRefImpl Sec) const; @@ -1094,6 +1107,43 @@ error_code ELFObjectFile template error_code ELFObjectFile + ::isSectionRequiredForExecution(DataRefImpl Sec, + bool &Result) const { + const Elf_Shdr *sec = reinterpret_cast(Sec.p); + if (sec->sh_flags & ELF::SHF_ALLOC) + Result = true; + else + Result = false; + return object_error::success; +} + +template +error_code ELFObjectFile + ::isSectionVirtual(DataRefImpl Sec, + bool &Result) const { + const Elf_Shdr *sec = reinterpret_cast(Sec.p); + if (sec->sh_type == ELF::SHT_NOBITS) + Result = true; + else + Result = false; + return object_error::success; +} + +template +error_code ELFObjectFile::isSectionZeroInit(DataRefImpl Sec, + bool &Result) const { + const Elf_Shdr *sec = reinterpret_cast(Sec.p); + // For ELF, all zero-init sections are virtual (that is, they occupy no space + // in the object image) and vice versa. + if (sec->sh_flags & ELF::SHT_NOBITS) + Result = true; + else + Result = false; + return object_error::success; +} + +template +error_code ELFObjectFile ::sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, bool &Result) const { diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index 1e409b28568..0b73f948316 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -72,6 +72,10 @@ protected: virtual error_code isSectionText(DataRefImpl Sec, bool &Res) const; virtual error_code isSectionData(DataRefImpl Sec, bool &Res) const; virtual error_code isSectionBSS(DataRefImpl Sec, bool &Res) const; + virtual error_code isSectionRequiredForExecution(DataRefImpl Sec, + bool &Res) const; + virtual error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const; + virtual error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const; virtual error_code sectionContainsSymbol(DataRefImpl DRI, DataRefImpl S, bool &Result) const; virtual relocation_iterator getSectionRelBegin(DataRefImpl Sec) const; diff --git a/include/llvm/Object/ObjectFile.h b/include/llvm/Object/ObjectFile.h index d8cda81533c..4dd7fb58130 100644 --- a/include/llvm/Object/ObjectFile.h +++ b/include/llvm/Object/ObjectFile.h @@ -158,11 +158,16 @@ public: error_code isText(bool &Result) const; error_code isData(bool &Result) const; error_code isBSS(bool &Result) const; + error_code isRequiredForExecution(bool &Result) const; + error_code isVirtual(bool &Result) const; + error_code isZeroInit(bool &Result) const; error_code containsSymbol(SymbolRef S, bool &Result) const; relocation_iterator begin_relocations() const; relocation_iterator end_relocations() const; + + DataRefImpl getRawDataRefImpl() const; }; typedef content_iterator section_iterator; @@ -217,6 +222,9 @@ public: /// Get symbol flags (bitwise OR of SymbolRef::Flags) error_code getFlags(uint32_t &Result) const; + /// @brief Return true for common symbols such as uninitialized globals + error_code isCommon(bool &Result) const; + /// @brief Get section this symbol is defined in reference to. Result is /// end_sections() if it is undefined or is an absolute symbol. error_code getSection(section_iterator &Result) const; @@ -299,6 +307,11 @@ protected: virtual error_code isSectionText(DataRefImpl Sec, bool &Res) const = 0; virtual error_code isSectionData(DataRefImpl Sec, bool &Res) const = 0; virtual error_code isSectionBSS(DataRefImpl Sec, bool &Res) const = 0; + virtual error_code isSectionRequiredForExecution(DataRefImpl Sec, + bool &Res) const = 0; + // A section is 'virtual' if its contents aren't present in the object image. + virtual error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const = 0; + virtual error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const = 0; virtual error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, bool &Result) const = 0; virtual relocation_iterator getSectionRelBegin(DataRefImpl Sec) const = 0; @@ -481,6 +494,18 @@ inline error_code SectionRef::isBSS(bool &Result) const { return OwningObject->isSectionBSS(SectionPimpl, Result); } +inline error_code SectionRef::isRequiredForExecution(bool &Result) const { + return OwningObject->isSectionRequiredForExecution(SectionPimpl, Result); +} + +inline error_code SectionRef::isVirtual(bool &Result) const { + return OwningObject->isSectionVirtual(SectionPimpl, Result); +} + +inline error_code SectionRef::isZeroInit(bool &Result) const { + return OwningObject->isSectionZeroInit(SectionPimpl, Result); +} + inline error_code SectionRef::containsSymbol(SymbolRef S, bool &Result) const { return OwningObject->sectionContainsSymbol(SectionPimpl, S.SymbolPimpl, Result); @@ -494,6 +519,9 @@ inline relocation_iterator SectionRef::end_relocations() const { return OwningObject->getSectionRelEnd(SectionPimpl); } +inline DataRefImpl SectionRef::getRawDataRefImpl() const { + return SectionPimpl; +} /// RelocationRef inline RelocationRef::RelocationRef(DataRefImpl RelocationP, diff --git a/lib/ExecutionEngine/MCJIT/MCJIT.cpp b/lib/ExecutionEngine/MCJIT/MCJIT.cpp index 80110e8294c..44f89cf7830 100644 --- a/lib/ExecutionEngine/MCJIT/MCJIT.cpp +++ b/lib/ExecutionEngine/MCJIT/MCJIT.cpp @@ -74,9 +74,9 @@ MCJIT::MCJIT(Module *m, TargetMachine *tm, TargetJITInfo &tji, OS.flush(); // Load the object into the dynamic linker. - // FIXME: It would be nice to avoid making yet another copy. - MemoryBuffer *MB = MemoryBuffer::getMemBufferCopy(StringRef(Buffer.data(), - Buffer.size())); + MemoryBuffer *MB = MemoryBuffer::getMemBuffer(StringRef(Buffer.data(), + Buffer.size()), + "", false); if (Dyld.loadObject(MB)) report_fatal_error(Dyld.getErrorString()); // Resolve any relocations. diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp index 7a2b8586119..63cec1aca3b 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp @@ -36,10 +36,9 @@ namespace { } } // end anonymous namespace - // Resolve the relocations for all symbols we currently know about. void RuntimeDyldImpl::resolveRelocations() { - // First, resolve relocations assotiated with external symbols. + // First, resolve relocations associated with external symbols. resolveSymbols(); // Just iterate over the sections we have and resolve all the relocations @@ -63,14 +62,18 @@ void RuntimeDyldImpl::mapSectionAddress(void *LocalAddress, bool RuntimeDyldImpl::loadObject(const MemoryBuffer *InputBuffer) { // FIXME: ObjectFile don't modify MemoryBuffer. // It should use const MemoryBuffer as parameter. - ObjectFile *obj - = ObjectFile::createObjectFile(const_cast(InputBuffer)); + OwningPtr obj(ObjectFile::createObjectFile( + const_cast(InputBuffer))); + if (!obj) + report_fatal_error("Unable to create object image from memory buffer!"); Arch = (Triple::ArchType)obj->getArch(); LocalSymbolMap LocalSymbols; // Functions and data symbols from the // object file. ObjSectionToIDMap LocalSections; // Used sections from the object file + CommonSymbolMap CommonSymbols; // Common symbols requiring allocation + uint64_t CommonSize = 0; error_code err; // Parse symbols @@ -83,36 +86,50 @@ bool RuntimeDyldImpl::loadObject(const MemoryBuffer *InputBuffer) { Check(i->getType(SymType)); Check(i->getName(Name)); - if (SymType == object::SymbolRef::ST_Function || - SymType == object::SymbolRef::ST_Data) { - uint64_t FileOffset; - uint32_t flags; - StringRef sData; - section_iterator si = obj->end_sections(); - Check(i->getFileOffset(FileOffset)); - Check(i->getFlags(flags)); - Check(i->getSection(si)); - if (si == obj->end_sections()) continue; - Check(si->getContents(sData)); - const uint8_t* SymPtr = (const uint8_t*)InputBuffer->getBufferStart() + - (uintptr_t)FileOffset; - uintptr_t SectOffset = (uintptr_t)(SymPtr - (const uint8_t*)sData.begin()); - unsigned SectionID - = findOrEmitSection(*si, - SymType == object::SymbolRef::ST_Function, - LocalSections); - bool isGlobal = flags & SymbolRef::SF_Global; - LocalSymbols[Name.data()] = SymbolLoc(SectionID, SectOffset); - DEBUG(dbgs() << "\tFileOffset: " << format("%p", (uintptr_t)FileOffset) - << " flags: " << flags - << " SID: " << SectionID - << " Offset: " << format("%p", SectOffset)); - if (isGlobal) - SymbolTable[Name] = SymbolLoc(SectionID, SectOffset); + uint32_t flags; + Check(i->getFlags(flags)); + + bool isCommon = flags & SymbolRef::SF_Common; + if (isCommon) { + // Add the common symbols to a list. We'll allocate them all below. + uint64_t Size = 0; + Check(i->getSize(Size)); + CommonSize += Size; + CommonSymbols[*i] = Size; + } else { + if (SymType == object::SymbolRef::ST_Function || + SymType == object::SymbolRef::ST_Data) { + uint64_t FileOffset; + StringRef sData; + section_iterator si = obj->end_sections(); + Check(i->getFileOffset(FileOffset)); + Check(i->getSection(si)); + if (si == obj->end_sections()) continue; + Check(si->getContents(sData)); + const uint8_t* SymPtr = (const uint8_t*)InputBuffer->getBufferStart() + + (uintptr_t)FileOffset; + uintptr_t SectOffset = (uintptr_t)(SymPtr - (const uint8_t*)sData.begin()); + unsigned SectionID = + findOrEmitSection(*si, + SymType == object::SymbolRef::ST_Function, + LocalSections); + bool isGlobal = flags & SymbolRef::SF_Global; + LocalSymbols[Name.data()] = SymbolLoc(SectionID, SectOffset); + DEBUG(dbgs() << "\tFileOffset: " << format("%p", (uintptr_t)FileOffset) + << " flags: " << flags + << " SID: " << SectionID + << " Offset: " << format("%p", SectOffset)); + if (isGlobal) + SymbolTable[Name] = SymbolLoc(SectionID, SectOffset); + } } DEBUG(dbgs() << "\tType: " << SymType << " Name: " << Name << "\n"); } + // Allocate common symbols + if (CommonSize != 0) + emitCommonSymbols(CommonSymbols, CommonSize, LocalSymbols); + // Parse and proccess relocations DEBUG(dbgs() << "Parse relocations:\n"); for (section_iterator si = obj->begin_sections(), @@ -150,6 +167,38 @@ bool RuntimeDyldImpl::loadObject(const MemoryBuffer *InputBuffer) { return false; } +unsigned RuntimeDyldImpl::emitCommonSymbols(const CommonSymbolMap &Map, + uint64_t TotalSize, + LocalSymbolMap &LocalSymbols) { + // Allocate memory for the section + unsigned SectionID = Sections.size(); + uint8_t *Addr = MemMgr->allocateDataSection(TotalSize, sizeof(void*), + SectionID); + if (!Addr) + report_fatal_error("Unable to allocate memory for common symbols!"); + uint64_t Offset = 0; + Sections.push_back(SectionEntry(Addr, TotalSize, TotalSize, 0)); + memset(Addr, 0, TotalSize); + + DEBUG(dbgs() << "emitCommonSection SectionID: " << SectionID + << " new addr: " << format("%p", Addr) + << " DataSize: " << TotalSize + << "\n"); + + // Assign the address of each symbol + for (CommonSymbolMap::const_iterator it = Map.begin(), itEnd = Map.end(); + it != itEnd; it++) { + uint64_t Size = it->second; + StringRef Name; + it->first.getName(Name); + LocalSymbols[Name.data()] = SymbolLoc(SectionID, Offset); + Offset += Size; + Addr += Size; + } + + return SectionID; +} + unsigned RuntimeDyldImpl::emitSection(const SectionRef &Section, bool IsCode) { @@ -158,7 +207,7 @@ unsigned RuntimeDyldImpl::emitSection(const SectionRef &Section, error_code err; if (StubSize > 0) { for (relocation_iterator i = Section.begin_relocations(), - e = Section.end_relocations(); i != e; i.increment(err)) + e = Section.end_relocations(); i != e; i.increment(err), Check(err)) StubBufSize += StubSize; } StringRef data; @@ -167,22 +216,63 @@ unsigned RuntimeDyldImpl::emitSection(const SectionRef &Section, Check(Section.getAlignment(Alignment64)); unsigned Alignment = (unsigned)Alignment64 & 0xffffffffL; - unsigned DataSize = data.size(); - unsigned Allocate = DataSize + StubBufSize; + bool IsRequired; + bool IsVirtual; + bool IsZeroInit; + uint64_t DataSize; + Check(Section.isRequiredForExecution(IsRequired)); + Check(Section.isVirtual(IsVirtual)); + Check(Section.isZeroInit(IsZeroInit)); + Check(Section.getSize(DataSize)); + + unsigned Allocate; unsigned SectionID = Sections.size(); - const char *pData = data.data(); - uint8_t *Addr = IsCode - ? MemMgr->allocateCodeSection(Allocate, Alignment, SectionID) - : MemMgr->allocateDataSection(Allocate, Alignment, SectionID); - - memcpy(Addr, pData, DataSize); - DEBUG(dbgs() << "emitSection SectionID: " << SectionID - << " obj addr: " << format("%p", pData) - << " new addr: " << format("%p", Addr) - << " DataSize: " << DataSize - << " StubBufSize: " << StubBufSize - << " Allocate: " << Allocate - << "\n"); + uint8_t *Addr; + const char *pData = 0; + + // Some sections, such as debug info, don't need to be loaded for execution. + // Leave those where they are. + if (IsRequired) { + Allocate = DataSize + StubBufSize; + Addr = IsCode + ? MemMgr->allocateCodeSection(Allocate, Alignment, SectionID) + : MemMgr->allocateDataSection(Allocate, Alignment, SectionID); + if (!Addr) + report_fatal_error("Unable to allocate section memory!"); + + // Virtual sections have no data in the object image, so leave pData = 0 + if (!IsVirtual) + pData = data.data(); + + // Zero-initialize or copy the data from the image + if (IsZeroInit || IsVirtual) + memset(Addr, 0, DataSize); + else + memcpy(Addr, pData, DataSize); + + DEBUG(dbgs() << "emitSection SectionID: " << SectionID + << " obj addr: " << format("%p", pData) + << " new addr: " << format("%p", Addr) + << " DataSize: " << DataSize + << " StubBufSize: " << StubBufSize + << " Allocate: " << Allocate + << "\n"); + } + else { + // Even if we didn't load the section, we need to record an entry for it + // to handle later processing (and by 'handle' I mean don't do anything + // with these sections). + Allocate = 0; + Addr = 0; + DEBUG(dbgs() << "emitSection SectionID: " << SectionID + << " obj addr: " << format("%p", data.data()) + << " new addr: 0" + << " DataSize: " << DataSize + << " StubBufSize: " << StubBufSize + << " Allocate: " << Allocate + << "\n"); + } + Sections.push_back(SectionEntry(Addr, Allocate, DataSize,(uintptr_t)pData)); return SectionID; } @@ -259,15 +349,18 @@ void RuntimeDyldImpl::reassignSectionAddress(unsigned SectionID, void RuntimeDyldImpl::resolveRelocationEntry(const RelocationEntry &RE, uint64_t Value) { - uint8_t *Target = Sections[RE.SectionID].Address + RE.Offset; - DEBUG(dbgs() << "\tSectionID: " << RE.SectionID - << " + " << RE.Offset << " (" << format("%p", Target) << ")" - << " Data: " << RE.Data - << " Addend: " << RE.Addend - << "\n"); - - resolveRelocation(Target, Sections[RE.SectionID].LoadAddress + RE.Offset, - Value, RE.Data, RE.Addend); + // Ignore relocations for sections that were not loaded + if (Sections[RE.SectionID].Address != 0) { + uint8_t *Target = Sections[RE.SectionID].Address + RE.Offset; + DEBUG(dbgs() << "\tSectionID: " << RE.SectionID + << " + " << RE.Offset << " (" << format("%p", Target) << ")" + << " Data: " << RE.Data + << " Addend: " << RE.Addend + << "\n"); + + resolveRelocation(Target, Sections[RE.SectionID].LoadAddress + RE.Offset, + Value, RE.Data, RE.Addend); + } } void RuntimeDyldImpl::resolveRelocationList(const RelocationList &Relocs, diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp index 9d46b21f59d..57fefee5ded 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp @@ -71,7 +71,8 @@ void RuntimeDyldELF::resolveX86Relocation(uint8_t *LocalAddress, switch (Type) { case ELF::R_386_32: { uint32_t *Target = (uint32_t*)(LocalAddress); - *Target = Value + Addend; + uint32_t Placeholder = *Target; + *Target = Placeholder + Value + Addend; break; } case ELF::R_386_PC32: { diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h index d6430a91c20..bf678af6ece 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h @@ -110,6 +110,9 @@ protected: StringMap SymbolTable; typedef DenseMap LocalSymbolMap; + // Keep a map of common symbols to their sizes + typedef std::map CommonSymbolMap; + // For each symbol, keep a list of relocations based on it. Anytime // its address is reassigned (the JIT re-compiled the function, e.g.), // the relocations get re-resolved. @@ -149,6 +152,12 @@ protected: return (uint8_t*)Sections[SectionID].Address; } + /// \brief Emits a section containing common symbols. + /// \return SectionID. + unsigned emitCommonSymbols(const CommonSymbolMap &Map, + uint64_t TotalSize, + LocalSymbolMap &Symbols); + /// \brief Emits section data from the object file to the MemoryManager. /// \param IsCode if it's true then allocateCodeSection() will be /// used for emmits, else allocateDataSection() will be used. diff --git a/lib/Object/COFFObjectFile.cpp b/lib/Object/COFFObjectFile.cpp index 53b15d07ea4..bd27a56e73b 100644 --- a/lib/Object/COFFObjectFile.cpp +++ b/lib/Object/COFFObjectFile.cpp @@ -356,6 +356,27 @@ error_code COFFObjectFile::isSectionBSS(DataRefImpl Sec, return object_error::success; } +error_code COFFObjectFile::isSectionRequiredForExecution(DataRefImpl Sec, + bool &Result) const { + // FIXME: Unimplemented + Result = true; + return object_error::success; +} + +error_code COFFObjectFile::isSectionVirtual(DataRefImpl Sec, + bool &Result) const { + const coff_section *sec = toSec(Sec); + Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA; + return object_error::success; +} + +error_code COFFObjectFile::isSectionZeroInit(DataRefImpl Sec, + bool &Result) const { + // FIXME: Unimplemented + Result = false; + return object_error::success; +} + error_code COFFObjectFile::sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, bool &Result) const { diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index ac90d5ccb4c..1078faa481a 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -175,7 +175,12 @@ error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI, BeginOffset = Entry->Value; SectionIndex = Entry->SectionIndex; if (!SectionIndex) { - Result = UnknownAddressOrSize; + uint32_t flags = SymbolRef::SF_None; + getSymbolFlags(DRI, flags); + if (flags & SymbolRef::SF_Common) + Result = Entry->Value; + else + Result = UnknownAddressOrSize; return object_error::success; } // Unfortunately symbols are unsorted so we need to touch all @@ -198,7 +203,12 @@ error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI, BeginOffset = Entry->Value; SectionIndex = Entry->SectionIndex; if (!SectionIndex) { - Result = UnknownAddressOrSize; + uint32_t flags = SymbolRef::SF_None; + getSymbolFlags(DRI, flags); + if (flags & SymbolRef::SF_Common) + Result = Entry->Value; + else + Result = UnknownAddressOrSize; return object_error::success; } // Unfortunately symbols are unsorted so we need to touch all @@ -265,19 +275,22 @@ error_code MachOObjectFile::getSymbolFlags(DataRefImpl DRI, uint32_t &Result) const { uint16_t MachOFlags; uint8_t MachOType; + uint8_t MachOSectionIndex; if (MachOObj->is64Bit()) { InMemoryStruct Entry; getSymbol64TableEntry(DRI, Entry); MachOFlags = Entry->Flags; MachOType = Entry->Type; + MachOSectionIndex = Entry->SectionIndex; } else { InMemoryStruct Entry; getSymbolTableEntry(DRI, Entry); MachOFlags = Entry->Flags; MachOType = Entry->Type; + MachOSectionIndex = Entry->SectionIndex; } - // TODO: Correctly set SF_ThreadLocal and SF_Common. + // TODO: Correctly set SF_ThreadLocal Result = SymbolRef::SF_None; if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined) @@ -286,8 +299,11 @@ error_code MachOObjectFile::getSymbolFlags(DataRefImpl DRI, if (MachOFlags & macho::STF_StabsEntryMask) Result |= SymbolRef::SF_FormatSpecific; - if (MachOType & MachO::NlistMaskExternal) + if (MachOType & MachO::NlistMaskExternal) { Result |= SymbolRef::SF_Global; + if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined) + Result |= SymbolRef::SF_Common; + } if (MachOFlags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef)) Result |= SymbolRef::SF_Weak; @@ -566,6 +582,37 @@ error_code MachOObjectFile::isSectionBSS(DataRefImpl DRI, return object_error::success; } +error_code MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec, + bool &Result) const { + // FIXME: Unimplemented + Result = true; + return object_error::success; +} + +error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec, + bool &Result) const { + // FIXME: Unimplemented + Result = false; + return object_error::success; +} + +error_code MachOObjectFile::isSectionZeroInit(DataRefImpl DRI, + bool &Result) const { + if (MachOObj->is64Bit()) { + InMemoryStruct Sect; + getSection64(DRI, Sect); + Result = (Sect->Flags & MachO::SectionTypeZeroFill || + Sect->Flags & MachO::SectionTypeZeroFillLarge); + } else { + InMemoryStruct Sect; + getSection(DRI, Sect); + Result = (Sect->Flags & MachO::SectionTypeZeroFill || + Sect->Flags & MachO::SectionTypeZeroFillLarge); + } + + return object_error::success; +} + error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, bool &Result) const { diff --git a/test/ExecutionEngine/2002-12-16-ArgTest.ll b/test/ExecutionEngine/2002-12-16-ArgTest.ll index b36feee516a..eb2fe8c0483 100644 --- a/test/ExecutionEngine/2002-12-16-ArgTest.ll +++ b/test/ExecutionEngine/2002-12-16-ArgTest.ll @@ -1,5 +1,4 @@ ; RUN: %lli %s > /dev/null -; XFAIL: mcjit @.LC0 = internal global [10 x i8] c"argc: %d\0A\00" ; <[10 x i8]*> [#uses=1] diff --git a/test/ExecutionEngine/2003-01-04-ArgumentBug.ll b/test/ExecutionEngine/2003-01-04-ArgumentBug.ll index 0cc0efd7eaf..3182193453a 100644 --- a/test/ExecutionEngine/2003-01-04-ArgumentBug.ll +++ b/test/ExecutionEngine/2003-01-04-ArgumentBug.ll @@ -1,6 +1,5 @@ ; RUN: %lli %s > /dev/null ; XFAIL: arm -; XFAIL: mcjit define i32 @foo(i32 %X, i32 %Y, double %A) { %cond212 = fcmp une double %A, 1.000000e+00 ; [#uses=1] diff --git a/test/ExecutionEngine/2003-01-04-LoopTest.ll b/test/ExecutionEngine/2003-01-04-LoopTest.ll index e4049a76e06..3e27e0607ba 100644 --- a/test/ExecutionEngine/2003-01-04-LoopTest.ll +++ b/test/ExecutionEngine/2003-01-04-LoopTest.ll @@ -1,6 +1,5 @@ ; RUN: %lli %s > /dev/null ; XFAIL: arm -; XFAIL: mcjit define i32 @main() { call i32 @mylog( i32 4 ) ; :1 [#uses=0] diff --git a/test/ExecutionEngine/2003-05-06-LivenessClobber.ll b/test/ExecutionEngine/2003-05-06-LivenessClobber.ll index 1e155ee20d5..6f61aa68b67 100644 --- a/test/ExecutionEngine/2003-05-06-LivenessClobber.ll +++ b/test/ExecutionEngine/2003-05-06-LivenessClobber.ll @@ -2,7 +2,6 @@ ; ; RUN: not %lli %s ; XFAIL: arm -; XFAIL: mcjit @test = global i64 0 ; [#uses=1] diff --git a/test/ExecutionEngine/2003-05-07-ArgumentTest.ll b/test/ExecutionEngine/2003-05-07-ArgumentTest.ll index 1a1ae5f56b9..236be18d96e 100644 --- a/test/ExecutionEngine/2003-05-07-ArgumentTest.ll +++ b/test/ExecutionEngine/2003-05-07-ArgumentTest.ll @@ -1,6 +1,5 @@ ; RUN: %lli %s test ; XFAIL: arm -; XFAIL: mcjit declare i32 @puts(i8*) diff --git a/test/ExecutionEngine/2003-08-21-EnvironmentTest.ll b/test/ExecutionEngine/2003-08-21-EnvironmentTest.ll index b56025a2796..60dc3d6b7d4 100644 --- a/test/ExecutionEngine/2003-08-21-EnvironmentTest.ll +++ b/test/ExecutionEngine/2003-08-21-EnvironmentTest.ll @@ -1,6 +1,5 @@ ; RUN: %lli %s > /dev/null ; XFAIL: arm -; XFAIL: mcjit ; ; Regression Test: EnvironmentTest.ll diff --git a/test/ExecutionEngine/2005-12-02-TailCallBug.ll b/test/ExecutionEngine/2005-12-02-TailCallBug.ll index 4d7bd895d24..8523b5e3f5b 100644 --- a/test/ExecutionEngine/2005-12-02-TailCallBug.ll +++ b/test/ExecutionEngine/2005-12-02-TailCallBug.ll @@ -1,7 +1,6 @@ ; PR672 ; RUN: %lli %s ; XFAIL: arm -; XFAIL: mcjit-ia32 define i32 @main() { %f = bitcast i32 (i32, i32*, i32)* @check_tail to i32* ; [#uses=1] diff --git a/test/ExecutionEngine/hello.ll b/test/ExecutionEngine/hello.ll index 4d1d9874bbf..f2c4a7f414d 100644 --- a/test/ExecutionEngine/hello.ll +++ b/test/ExecutionEngine/hello.ll @@ -1,6 +1,5 @@ ; RUN: %lli %s > /dev/null ; XFAIL: arm -; XFAIL: mcjit @.LC0 = internal global [12 x i8] c"Hello World\00" ; <[12 x i8]*> [#uses=1] diff --git a/test/ExecutionEngine/hello2.ll b/test/ExecutionEngine/hello2.ll index 05b4409302f..155ed41d7ca 100644 --- a/test/ExecutionEngine/hello2.ll +++ b/test/ExecutionEngine/hello2.ll @@ -1,6 +1,5 @@ ; RUN: %lli %s > /dev/null ; XFAIL: arm -; XFAIL: mcjit @X = global i32 7 ; [#uses=0] @msg = internal global [13 x i8] c"Hello World\0A\00" ; <[13 x i8]*> [#uses=1] diff --git a/test/ExecutionEngine/stubs.ll b/test/ExecutionEngine/stubs.ll index c1134e9ee06..b40e4be63d4 100644 --- a/test/ExecutionEngine/stubs.ll +++ b/test/ExecutionEngine/stubs.ll @@ -1,6 +1,5 @@ ; RUN: %lli -disable-lazy-compilation=false %s ; XFAIL: arm -; XFAIL: mcjit define i32 @main() nounwind { entry: diff --git a/test/ExecutionEngine/test-call-no-external-funcs.ll b/test/ExecutionEngine/test-call-no-external-funcs.ll index 0c98379a0bd..b2dd5325f11 100644 --- a/test/ExecutionEngine/test-call-no-external-funcs.ll +++ b/test/ExecutionEngine/test-call-no-external-funcs.ll @@ -1,6 +1,5 @@ ; RUN: %lli %s > /dev/null ; XFAIL: arm -; XFAIL: mcjit define i32 @_Z14func_exit_codev() nounwind uwtable { entry: diff --git a/test/ExecutionEngine/test-call.ll b/test/ExecutionEngine/test-call.ll index eaadbbae0a7..3fd39fe094f 100644 --- a/test/ExecutionEngine/test-call.ll +++ b/test/ExecutionEngine/test-call.ll @@ -1,6 +1,5 @@ ; RUN: %lli %s > /dev/null ; XFAIL: arm -; XFAIL: mcjit declare void @exit(i32) diff --git a/test/ExecutionEngine/test-common-symbols.ll b/test/ExecutionEngine/test-common-symbols.ll index 52ce7d1f60f..4dd926512ae 100644 --- a/test/ExecutionEngine/test-common-symbols.ll +++ b/test/ExecutionEngine/test-common-symbols.ll @@ -1,6 +1,5 @@ ; RUN: %lli -O0 -disable-lazy-compilation=false %s ; XFAIL: arm -; XFAIL: mcjit ; The intention of this test is to verify that symbols mapped to COMMON in ELF ; work as expected. diff --git a/test/ExecutionEngine/test-fp-no-external-funcs.ll b/test/ExecutionEngine/test-fp-no-external-funcs.ll index 6b8410a2257..61b12c2abeb 100644 --- a/test/ExecutionEngine/test-fp-no-external-funcs.ll +++ b/test/ExecutionEngine/test-fp-no-external-funcs.ll @@ -1,5 +1,4 @@ ; RUN: %lli %s > /dev/null -; XFAIL: mcjit define double @test(double* %DP, double %Arg) { %D = load double* %DP ; [#uses=1] diff --git a/test/ExecutionEngine/test-fp.ll b/test/ExecutionEngine/test-fp.ll index 3411ca1c766..2bf0210d8b0 100644 --- a/test/ExecutionEngine/test-fp.ll +++ b/test/ExecutionEngine/test-fp.ll @@ -1,5 +1,4 @@ ; RUN: %lli %s > /dev/null -; XFAIL: mcjit define double @test(double* %DP, double %Arg) { %D = load double* %DP ; [#uses=1] diff --git a/test/ExecutionEngine/test-global-init-nonzero.ll b/test/ExecutionEngine/test-global-init-nonzero.ll index a13bfc91f15..ef2d37b8919 100644 --- a/test/ExecutionEngine/test-global-init-nonzero.ll +++ b/test/ExecutionEngine/test-global-init-nonzero.ll @@ -1,6 +1,5 @@ ; RUN: %lli %s > /dev/null ; XFAIL: arm -; XFAIL: mcjit @count = global i32 1, align 4 diff --git a/test/ExecutionEngine/test-global.ll b/test/ExecutionEngine/test-global.ll index ce25cb23c74..2ea50dea99a 100644 --- a/test/ExecutionEngine/test-global.ll +++ b/test/ExecutionEngine/test-global.ll @@ -1,6 +1,5 @@ ; RUN: %lli %s > /dev/null ; XFAIL: arm -; XFAIL: mcjit @count = global i32 0, align 4 diff --git a/test/ExecutionEngine/test-loadstore.ll b/test/ExecutionEngine/test-loadstore.ll index b9b779802cc..75743146c6e 100644 --- a/test/ExecutionEngine/test-loadstore.ll +++ b/test/ExecutionEngine/test-loadstore.ll @@ -1,6 +1,5 @@ ; RUN: %lli %s > /dev/null ; XFAIL: arm -; XFAIL: mcjit-ia32 define void @test(i8* %P, i16* %P.upgrd.1, i32* %P.upgrd.2, i64* %P.upgrd.3) { %V = load i8* %P ; [#uses=1] -- 2.11.0