summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRafael Espindola <rafael.espindola@gmail.com>2014-01-24 21:32:21 +0000
committerRafael Espindola <rafael.espindola@gmail.com>2014-01-24 21:32:21 +0000
commit584fe2db6ad04974b569da2d90860cc2b75c025b (patch)
treedb2c62aeccda78b0669885a72340980b44065b53
parent0078935812a53b12d257b94343ea20e78e6c9130 (diff)
downloadllvm-584fe2db6ad04974b569da2d90860cc2b75c025b.tar.gz
llvm-584fe2db6ad04974b569da2d90860cc2b75c025b.tar.bz2
llvm-584fe2db6ad04974b569da2d90860cc2b75c025b.tar.xz
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
-rw-r--r--include/llvm/Object/Binary.h3
-rw-r--r--include/llvm/Object/COFF.h2
-rw-r--r--include/llvm/Object/ELFObjectFile.h7
-rw-r--r--include/llvm/Object/MachO.h2
-rw-r--r--include/llvm/Object/ObjectFile.h13
-rw-r--r--lib/Object/Binary.cpp8
-rw-r--r--lib/Object/COFFObjectFile.cpp16
-rw-r--r--lib/Object/ELFObjectFile.cpp27
-rw-r--r--lib/Object/MachOObjectFile.cpp19
-rw-r--r--lib/Object/ObjectFile.cpp16
-rw-r--r--tools/llvm-ar/llvm-ar.cpp70
11 files changed, 98 insertions, 85 deletions
diff --git a/include/llvm/Object/Binary.h b/include/llvm/Object/Binary.h
index 7742f83cd0..420cc9bba8 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 1514f279b4..38ea814ed1 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 a536594ee2..17d2ec7b2f 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<ELFT>::getRela(DataRefImpl Rela) const {
}
template <class ELFT>
-ELFObjectFile<ELFT>::ELFObjectFile(MemoryBuffer *Object, error_code &ec)
+ELFObjectFile<ELFT>::ELFObjectFile(MemoryBuffer *Object, error_code &ec,
+ bool BufferOwned)
: ObjectFile(getELFType(static_cast<endianness>(ELFT::TargetEndianness) ==
support::little,
ELFT::Is64Bits),
- Object),
+ Object, BufferOwned),
EF(Object, ec) {}
template <class ELFT>
diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h
index 100613ac8c..98c36b07bd 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 77833cbf94..806de34e76 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<const uint8_t *>(Data->getBufferStart());
@@ -379,7 +379,7 @@ public:
/// @brief Create ObjectFile from path.
static ErrorOr<ObjectFile *> createObjectFile(StringRef ObjectPath);
static ErrorOr<ObjectFile *>
- 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<ObjectFile *> createCOFFObjectFile(MemoryBuffer *Object);
- static ErrorOr<ObjectFile *> createELFObjectFile(MemoryBuffer *Object);
- static ErrorOr<ObjectFile *> createMachOObjectFile(MemoryBuffer *Object);
+ static ErrorOr<ObjectFile *> createCOFFObjectFile(MemoryBuffer *Object,
+ bool BufferOwned = true);
+ static ErrorOr<ObjectFile *> createELFObjectFile(MemoryBuffer *Object,
+ bool BufferOwned = true);
+ static ErrorOr<ObjectFile *> createMachOObjectFile(MemoryBuffer *Object,
+ bool BufferOwned = true);
};
// Inline function definitions.
diff --git a/lib/Object/Binary.cpp b/lib/Object/Binary.cpp
index a0c412a64b..a2f4ec9a0b 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 a7b0688500..c28f88484f 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 *> ObjectFile::createCOFFObjectFile(MemoryBuffer *Object) {
+ErrorOr<ObjectFile *> ObjectFile::createCOFFObjectFile(MemoryBuffer *Object,
+ bool BufferOwned) {
error_code EC;
- OwningPtr<COFFObjectFile> Ret(new COFFObjectFile(Object, EC));
+ OwningPtr<COFFObjectFile> 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 2736bc42f2..0d90c906cc 100644
--- a/lib/Object/ELFObjectFile.cpp
+++ b/lib/Object/ELFObjectFile.cpp
@@ -17,7 +17,8 @@
namespace llvm {
using namespace object;
-ErrorOr<ObjectFile *> ObjectFile::createELFObjectFile(MemoryBuffer *Obj) {
+ErrorOr<ObjectFile *> ObjectFile::createELFObjectFile(MemoryBuffer *Obj,
+ bool BufferOwned) {
std::pair<unsigned char, unsigned char> Ident = getElfArchType(Obj);
std::size_t MaxAlignment =
1ULL << countTrailingZeros(uintptr_t(Obj->getBufferStart()));
@@ -27,41 +28,49 @@ ErrorOr<ObjectFile *> 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<ELFType<support::little, 4, false> >(Obj, EC));
+ R.reset(new ELFObjectFile<ELFType<support::little, 4, false> >(
+ Obj, EC, BufferOwned));
else
#endif
if (MaxAlignment >= 2)
- R.reset(new ELFObjectFile<ELFType<support::little, 2, false> >(Obj, EC));
+ R.reset(new ELFObjectFile<ELFType<support::little, 2, false> >(
+ 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<ELFType<support::big, 4, false> >(Obj, EC));
+ R.reset(new ELFObjectFile<ELFType<support::big, 4, false> >(Obj, EC,
+ BufferOwned));
else
#endif
if (MaxAlignment >= 2)
- R.reset(new ELFObjectFile<ELFType<support::big, 2, false> >(Obj, EC));
+ R.reset(new ELFObjectFile<ELFType<support::big, 2, false> >(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<ELFType<support::big, 8, true> >(Obj, EC));
+ R.reset(new ELFObjectFile<ELFType<support::big, 8, true> >(Obj, EC,
+ BufferOwned));
else
#endif
if (MaxAlignment >= 2)
- R.reset(new ELFObjectFile<ELFType<support::big, 2, true> >(Obj, EC));
+ R.reset(new ELFObjectFile<ELFType<support::big, 2, true> >(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<ELFType<support::little, 8, true> >(Obj, EC));
+ R.reset(new ELFObjectFile<ELFType<support::little, 8, true> >(
+ Obj, EC, BufferOwned));
else
#endif
if (MaxAlignment >= 2)
- R.reset(new ELFObjectFile<ELFType<support::little, 2, true> >(Obj, EC));
+ R.reset(new ELFObjectFile<ELFType<support::little, 2, true> >(
+ Obj, EC, BufferOwned));
else
llvm_unreachable("Invalid alignment for ELF file!");
}
diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp
index a930117019..2409314e12 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 *> ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) {
+ErrorOr<ObjectFile *> ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer,
+ bool BufferOwned) {
StringRef Magic = Buffer->getBuffer().slice(0, 4);
error_code EC;
OwningPtr<MachOObjectFile> 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 6b14e78ff3..2e6b9e6505 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 *> ObjectFile::createObjectFile(MemoryBuffer *Object,
+ bool BufferOwned,
sys::fs::file_magic Type) {
- OwningPtr<MemoryBuffer> ScopedObj(Object);
if (Type == sys::fs::file_magic::unknown)
Type = sys::fs::identify_magic(Object->getBuffer());
@@ -49,12 +49,14 @@ ErrorOr<ObjectFile *> 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 *> 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 b2081e1a7b..d8c75f2fae 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<NewArchiveIterator> Members,
+ ArrayRef<OwningPtr<MemoryBuffer> > Buffers,
std::vector<std::pair<unsigned, unsigned> > &MemberOffsetRefs) {
unsigned StartOffset = 0;
unsigned MemberNum = 0;
@@ -700,36 +701,13 @@ static void writeSymbolTable(
for (ArrayRef<NewArchiveIterator>::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<MemoryBuffer> File;
- failIfError(MemoryBuffer::getOpenFile(FD, Filename, File,
- Status.getSize(), false),
- Filename);
+ const OwningPtr<MemoryBuffer> &MemberBuffer = Buffers[MemberNum];
+ ErrorOr<object::ObjectFile *> 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<object::ObjectFile *> ObjOrErr =
- object::ObjectFile::createObjectFile(File.take()))
- Obj = ObjOrErr.get();
- else
- Obj = NULL;
- } else {
- object::Archive::child_iterator OldMember = I->getOld();
- OwningPtr<object::Binary> Binary;
- error_code EC = OldMember->getAsBinary(Binary);
- if (EC) { // FIXME: check only for "not an object file" errors.
- Obj = NULL;
- } else {
- Obj = dyn_cast<object::ObjectFile>(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<std::pair<unsigned, unsigned> > MemberOffsetRefs;
+ std::vector<OwningPtr<MemoryBuffer> > MemberBuffers;
+ MemberBuffers.resize(NewMembers.size());
+
+ for (unsigned I = 0, N = NewMembers.size(); I < N; ++I) {
+ OwningPtr<MemoryBuffer> &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<unsigned> StringMapIndexes;
@@ -825,16 +824,11 @@ static void performWriteOperation(ArchiveOperation Operation,
}
Out.seek(Pos);
+ const OwningPtr<MemoryBuffer> &File = MemberBuffers[MemberNum];
if (I->isNewMember()) {
const char *FileName = I->getNew();
- int FD = I->getFD();
const sys::fs::file_status &Status = I->getStatus();
- OwningPtr<MemoryBuffer> 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';
}