From: Rafael Espindola Date: Fri, 24 Jan 2014 21:32:21 +0000 (+0000) Subject: Make ObjectFile ownership of the MemoryBuffer optional. X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=584fe2db6ad04974b569da2d90860cc2b75c025b;p=oota-llvm.git Make ObjectFile ownership of the MemoryBuffer optional. This allows llvm-ar to mmap the input files only once. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@200040 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/Object/Binary.h b/include/llvm/Object/Binary.h index 7742f83cd08..420cc9bba8f 100644 --- a/include/llvm/Object/Binary.h +++ b/include/llvm/Object/Binary.h @@ -31,11 +31,12 @@ private: Binary(const Binary &other) LLVM_DELETED_FUNCTION; unsigned int TypeID; + bool BufferOwned; protected: MemoryBuffer *Data; - Binary(unsigned int Type, MemoryBuffer *Source); + Binary(unsigned int Type, MemoryBuffer *Source, bool BufferOwned = true); enum { ID_Archive, diff --git a/include/llvm/Object/COFF.h b/include/llvm/Object/COFF.h index 1514f279b42..38ea814ed1c 100644 --- a/include/llvm/Object/COFF.h +++ b/include/llvm/Object/COFF.h @@ -320,7 +320,7 @@ protected: StringRef &Result) const; public: - COFFObjectFile(MemoryBuffer *Object, error_code &ec); + COFFObjectFile(MemoryBuffer *Object, error_code &EC, bool BufferOwned = true); virtual symbol_iterator begin_symbols() const; virtual symbol_iterator end_symbols() const; virtual symbol_iterator begin_dynamic_symbols() const; diff --git a/include/llvm/Object/ELFObjectFile.h b/include/llvm/Object/ELFObjectFile.h index a536594ee2f..17d2ec7b2f9 100644 --- a/include/llvm/Object/ELFObjectFile.h +++ b/include/llvm/Object/ELFObjectFile.h @@ -165,7 +165,7 @@ protected: bool isDyldELFObject; public: - ELFObjectFile(MemoryBuffer *Object, error_code &ec); + ELFObjectFile(MemoryBuffer *Object, error_code &EC, bool BufferOwned = true); const Elf_Sym *getSymbol(DataRefImpl Symb) const; @@ -813,11 +813,12 @@ ELFObjectFile::getRela(DataRefImpl Rela) const { } template -ELFObjectFile::ELFObjectFile(MemoryBuffer *Object, error_code &ec) +ELFObjectFile::ELFObjectFile(MemoryBuffer *Object, error_code &ec, + bool BufferOwned) : ObjectFile(getELFType(static_cast(ELFT::TargetEndianness) == support::little, ELFT::Is64Bits), - Object), + Object, BufferOwned), EF(Object, ec) {} template diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index 100613ac8cc..98c36b07bd4 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -57,7 +57,7 @@ public: }; MachOObjectFile(MemoryBuffer *Object, bool IsLittleEndian, bool Is64Bits, - error_code &ec); + error_code &EC, bool BufferOwned = true); virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const; virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const; diff --git a/include/llvm/Object/ObjectFile.h b/include/llvm/Object/ObjectFile.h index 77833cbf940..806de34e76a 100644 --- a/include/llvm/Object/ObjectFile.h +++ b/include/llvm/Object/ObjectFile.h @@ -270,7 +270,7 @@ class ObjectFile : public Binary { ObjectFile(const ObjectFile &other) LLVM_DELETED_FUNCTION; protected: - ObjectFile(unsigned int Type, MemoryBuffer *source); + ObjectFile(unsigned int Type, MemoryBuffer *Source, bool BufferOwned = true); const uint8_t *base() const { return reinterpret_cast(Data->getBufferStart()); @@ -379,7 +379,7 @@ public: /// @brief Create ObjectFile from path. static ErrorOr createObjectFile(StringRef ObjectPath); static ErrorOr - createObjectFile(MemoryBuffer *Object, + createObjectFile(MemoryBuffer *Object, bool BufferOwned = true, sys::fs::file_magic Type = sys::fs::file_magic::unknown); static inline bool classof(const Binary *v) { @@ -387,9 +387,12 @@ public: } public: - static ErrorOr createCOFFObjectFile(MemoryBuffer *Object); - static ErrorOr createELFObjectFile(MemoryBuffer *Object); - static ErrorOr createMachOObjectFile(MemoryBuffer *Object); + static ErrorOr createCOFFObjectFile(MemoryBuffer *Object, + bool BufferOwned = true); + static ErrorOr createELFObjectFile(MemoryBuffer *Object, + bool BufferOwned = true); + static ErrorOr createMachOObjectFile(MemoryBuffer *Object, + bool BufferOwned = true); }; // Inline function definitions. diff --git a/lib/Object/Binary.cpp b/lib/Object/Binary.cpp index a0c412a64b2..a2f4ec9a0b8 100644 --- a/lib/Object/Binary.cpp +++ b/lib/Object/Binary.cpp @@ -26,12 +26,12 @@ using namespace llvm; using namespace object; Binary::~Binary() { - delete Data; + if (BufferOwned) + delete Data; } -Binary::Binary(unsigned int Type, MemoryBuffer *Source) - : TypeID(Type) - , Data(Source) {} +Binary::Binary(unsigned int Type, MemoryBuffer *Source, bool BufferOwned) + : TypeID(Type), BufferOwned(BufferOwned), Data(Source) {} StringRef Binary::getData() const { return Data->getBuffer(); diff --git a/lib/Object/COFFObjectFile.cpp b/lib/Object/COFFObjectFile.cpp index a7b06885008..c28f88484fb 100644 --- a/lib/Object/COFFObjectFile.cpp +++ b/lib/Object/COFFObjectFile.cpp @@ -463,11 +463,12 @@ error_code COFFObjectFile::initExportTablePtr() { return object_error::success; } -COFFObjectFile::COFFObjectFile(MemoryBuffer *Object, error_code &EC) - : ObjectFile(Binary::ID_COFF, Object), COFFHeader(0), PE32Header(0), - DataDirectory(0), SectionTable(0), SymbolTable(0), StringTable(0), - StringTableSize(0), ImportDirectory(0), NumberOfImportDirectory(0), - ExportDirectory(0) { +COFFObjectFile::COFFObjectFile(MemoryBuffer *Object, error_code &EC, + bool BufferOwned) + : ObjectFile(Binary::ID_COFF, Object, BufferOwned), COFFHeader(0), + PE32Header(0), DataDirectory(0), SectionTable(0), SymbolTable(0), + StringTable(0), StringTableSize(0), ImportDirectory(0), + NumberOfImportDirectory(0), ExportDirectory(0) { // Check that we at least have enough room for a header. if (!checkSize(Data, EC, sizeof(coff_file_header))) return; @@ -1015,9 +1016,10 @@ error_code ExportDirectoryEntryRef::getSymbolName(StringRef &Result) const { return object_error::success; } -ErrorOr ObjectFile::createCOFFObjectFile(MemoryBuffer *Object) { +ErrorOr ObjectFile::createCOFFObjectFile(MemoryBuffer *Object, + bool BufferOwned) { error_code EC; - OwningPtr Ret(new COFFObjectFile(Object, EC)); + OwningPtr Ret(new COFFObjectFile(Object, EC, BufferOwned)); if (EC) return EC; return Ret.take(); diff --git a/lib/Object/ELFObjectFile.cpp b/lib/Object/ELFObjectFile.cpp index 2736bc42f2e..0d90c906ccb 100644 --- a/lib/Object/ELFObjectFile.cpp +++ b/lib/Object/ELFObjectFile.cpp @@ -17,7 +17,8 @@ namespace llvm { using namespace object; -ErrorOr ObjectFile::createELFObjectFile(MemoryBuffer *Obj) { +ErrorOr ObjectFile::createELFObjectFile(MemoryBuffer *Obj, + bool BufferOwned) { std::pair Ident = getElfArchType(Obj); std::size_t MaxAlignment = 1ULL << countTrailingZeros(uintptr_t(Obj->getBufferStart())); @@ -27,41 +28,49 @@ ErrorOr ObjectFile::createELFObjectFile(MemoryBuffer *Obj) { if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2LSB) #if !LLVM_IS_UNALIGNED_ACCESS_FAST if (MaxAlignment >= 4) - R.reset(new ELFObjectFile >(Obj, EC)); + R.reset(new ELFObjectFile >( + Obj, EC, BufferOwned)); else #endif if (MaxAlignment >= 2) - R.reset(new ELFObjectFile >(Obj, EC)); + R.reset(new ELFObjectFile >( + Obj, EC, BufferOwned)); else llvm_unreachable("Invalid alignment for ELF file!"); 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)); + R.reset(new ELFObjectFile >(Obj, EC, + BufferOwned)); else #endif if (MaxAlignment >= 2) - R.reset(new ELFObjectFile >(Obj, EC)); + R.reset(new ELFObjectFile >(Obj, EC, + BufferOwned)); else llvm_unreachable("Invalid alignment for ELF file!"); 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)); + R.reset(new ELFObjectFile >(Obj, EC, + BufferOwned)); else #endif if (MaxAlignment >= 2) - R.reset(new ELFObjectFile >(Obj, EC)); + R.reset(new ELFObjectFile >(Obj, EC, + BufferOwned)); else llvm_unreachable("Invalid alignment for ELF file!"); 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)); + R.reset(new ELFObjectFile >( + Obj, EC, BufferOwned)); else #endif if (MaxAlignment >= 2) - R.reset(new ELFObjectFile >(Obj, EC)); + R.reset(new ELFObjectFile >( + Obj, EC, BufferOwned)); else llvm_unreachable("Invalid alignment for ELF file!"); } diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index a930117019e..2409314e12c 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -419,10 +419,10 @@ static uint32_t getSectionFlags(const MachOObjectFile *O, return Sect.flags; } -MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, - bool IsLittleEndian, bool Is64bits, - error_code &ec) - : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object), +MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, bool IsLittleEndian, + bool Is64bits, error_code &EC, + bool BufferOwned) + : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object, BufferOwned), SymtabLoadCmd(NULL), DysymtabLoadCmd(NULL), DataInCodeLoadCmd(NULL) { uint32_t LoadCommandCount = this->getHeader().ncmds; MachO::LoadCommandType SegmentLoadType = is64Bit() ? @@ -1582,18 +1582,19 @@ void MachOObjectFile::ReadULEB128s(uint64_t Index, } } -ErrorOr ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) { +ErrorOr ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer, + bool BufferOwned) { StringRef Magic = Buffer->getBuffer().slice(0, 4); error_code EC; OwningPtr Ret; if (Magic == "\xFE\xED\xFA\xCE") - Ret.reset(new MachOObjectFile(Buffer, false, false, EC)); + Ret.reset(new MachOObjectFile(Buffer, false, false, EC, BufferOwned)); else if (Magic == "\xCE\xFA\xED\xFE") - Ret.reset(new MachOObjectFile(Buffer, true, false, EC)); + Ret.reset(new MachOObjectFile(Buffer, true, false, EC, BufferOwned)); else if (Magic == "\xFE\xED\xFA\xCF") - Ret.reset(new MachOObjectFile(Buffer, false, true, EC)); + Ret.reset(new MachOObjectFile(Buffer, false, true, EC, BufferOwned)); else if (Magic == "\xCF\xFA\xED\xFE") - Ret.reset(new MachOObjectFile(Buffer, true, true, EC)); + Ret.reset(new MachOObjectFile(Buffer, true, true, EC, BufferOwned)); else { delete Buffer; return object_error::parse_failed; diff --git a/lib/Object/ObjectFile.cpp b/lib/Object/ObjectFile.cpp index 6b14e78ff3d..2e6b9e6505a 100644 --- a/lib/Object/ObjectFile.cpp +++ b/lib/Object/ObjectFile.cpp @@ -23,9 +23,9 @@ using namespace object; void ObjectFile::anchor() { } -ObjectFile::ObjectFile(unsigned int Type, MemoryBuffer *source) - : Binary(Type, source) { -} +ObjectFile::ObjectFile(unsigned int Type, MemoryBuffer *Source, + bool BufferOwned) + : Binary(Type, Source, BufferOwned) {} error_code ObjectFile::getSymbolAlignment(DataRefImpl DRI, uint32_t &Result) const { @@ -38,8 +38,8 @@ section_iterator ObjectFile::getRelocatedSection(DataRefImpl Sec) const { } ErrorOr ObjectFile::createObjectFile(MemoryBuffer *Object, + bool BufferOwned, sys::fs::file_magic Type) { - OwningPtr ScopedObj(Object); if (Type == sys::fs::file_magic::unknown) Type = sys::fs::identify_magic(Object->getBuffer()); @@ -49,12 +49,14 @@ ErrorOr ObjectFile::createObjectFile(MemoryBuffer *Object, case sys::fs::file_magic::archive: case sys::fs::file_magic::macho_universal_binary: case sys::fs::file_magic::windows_resource: + if (BufferOwned) + delete Object; return object_error::invalid_file_type; case sys::fs::file_magic::elf_relocatable: case sys::fs::file_magic::elf_executable: case sys::fs::file_magic::elf_shared_object: case sys::fs::file_magic::elf_core: - return createELFObjectFile(ScopedObj.take()); + return createELFObjectFile(Object, BufferOwned); case sys::fs::file_magic::macho_object: case sys::fs::file_magic::macho_executable: case sys::fs::file_magic::macho_fixed_virtual_memory_shared_lib: @@ -65,11 +67,11 @@ ErrorOr ObjectFile::createObjectFile(MemoryBuffer *Object, case sys::fs::file_magic::macho_bundle: case sys::fs::file_magic::macho_dynamically_linked_shared_lib_stub: case sys::fs::file_magic::macho_dsym_companion: - return createMachOObjectFile(ScopedObj.take()); + return createMachOObjectFile(Object, BufferOwned); case sys::fs::file_magic::coff_object: case sys::fs::file_magic::coff_import_library: case sys::fs::file_magic::pecoff_executable: - return createCOFFObjectFile(ScopedObj.take()); + return createCOFFObjectFile(Object, BufferOwned); } llvm_unreachable("Unexpected Object File Type"); } diff --git a/tools/llvm-ar/llvm-ar.cpp b/tools/llvm-ar/llvm-ar.cpp index b2081e1a7b0..d8c75f2fae1 100644 --- a/tools/llvm-ar/llvm-ar.cpp +++ b/tools/llvm-ar/llvm-ar.cpp @@ -692,6 +692,7 @@ static void writeStringTable(raw_fd_ostream &Out, static void writeSymbolTable( raw_fd_ostream &Out, ArrayRef Members, + ArrayRef > Buffers, std::vector > &MemberOffsetRefs) { unsigned StartOffset = 0; unsigned MemberNum = 0; @@ -700,36 +701,13 @@ static void writeSymbolTable( for (ArrayRef::iterator I = Members.begin(), E = Members.end(); I != E; ++I, ++MemberNum) { - object::ObjectFile *Obj; - if (I->isNewMember()) { - const char *Filename = I->getNew(); - int FD = I->getFD(); - const sys::fs::file_status &Status = I->getStatus(); - - OwningPtr File; - failIfError(MemoryBuffer::getOpenFile(FD, Filename, File, - Status.getSize(), false), - Filename); + const OwningPtr &MemberBuffer = Buffers[MemberNum]; + ErrorOr ObjOrErr = + object::ObjectFile::createObjectFile(MemberBuffer.get(), false); + if (!ObjOrErr) + continue; // FIXME: check only for "not an object file" errors. + object::ObjectFile *Obj = ObjOrErr.get(); - if (ErrorOr ObjOrErr = - object::ObjectFile::createObjectFile(File.take())) - Obj = ObjOrErr.get(); - else - Obj = NULL; - } else { - object::Archive::child_iterator OldMember = I->getOld(); - OwningPtr Binary; - error_code EC = OldMember->getAsBinary(Binary); - if (EC) { // FIXME: check only for "not an object file" errors. - Obj = NULL; - } else { - Obj = dyn_cast(Binary.get()); - if (Obj) - Binary.take(); - } - } - if (!Obj) - continue; DeleteIt.push_back(Obj); if (!StartOffset) { printMemberHeader(Out, "", sys::TimeValue::now(), 0, 0, 0, 0); @@ -800,8 +778,29 @@ static void performWriteOperation(ArchiveOperation Operation, std::vector > MemberOffsetRefs; + std::vector > MemberBuffers; + MemberBuffers.resize(NewMembers.size()); + + for (unsigned I = 0, N = NewMembers.size(); I < N; ++I) { + OwningPtr &MemberBuffer = MemberBuffers[I]; + NewArchiveIterator &Member = NewMembers[I]; + + if (Member.isNewMember()) { + const char *Filename = Member.getNew(); + int FD = Member.getFD(); + const sys::fs::file_status &Status = Member.getStatus(); + failIfError(MemoryBuffer::getOpenFile(FD, Filename, MemberBuffer, + Status.getSize(), false), + Filename); + + } else { + object::Archive::child_iterator OldMember = Member.getOld(); + failIfError(OldMember->getMemoryBuffer(MemberBuffer)); + } + } + if (Symtab) { - writeSymbolTable(Out, NewMembers, MemberOffsetRefs); + writeSymbolTable(Out, NewMembers, MemberBuffers, MemberOffsetRefs); } std::vector StringMapIndexes; @@ -825,16 +824,11 @@ static void performWriteOperation(ArchiveOperation Operation, } Out.seek(Pos); + const OwningPtr &File = MemberBuffers[MemberNum]; if (I->isNewMember()) { const char *FileName = I->getNew(); - int FD = I->getFD(); const sys::fs::file_status &Status = I->getStatus(); - OwningPtr File; - failIfError(MemoryBuffer::getOpenFile(FD, FileName, File, - Status.getSize(), false), - FileName); - StringRef Name = sys::path::filename(FileName); if (Name.size() < 16) printMemberHeader(Out, Name, Status.getLastModificationTime(), @@ -845,7 +839,6 @@ static void performWriteOperation(ArchiveOperation Operation, Status.getLastModificationTime(), Status.getUser(), Status.getGroup(), Status.permissions(), Status.getSize()); - Out << File->getBuffer(); } else { object::Archive::child_iterator OldMember = I->getOld(); StringRef Name = I->getName(); @@ -859,9 +852,10 @@ static void performWriteOperation(ArchiveOperation Operation, OldMember->getLastModified(), OldMember->getUID(), OldMember->getGID(), OldMember->getAccessMode(), OldMember->getSize()); - Out << OldMember->getBuffer(); } + Out << File->getBuffer(); + if (Out.tell() % 2) Out << '\n'; }