mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-25 12:12:47 +01:00
Make ObjectFile ownership of the MemoryBuffer optional.
This allows llvm-ar to mmap the input files only once. llvm-svn: 200040
This commit is contained in:
parent
4f80cb3b52
commit
a11df1035e
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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>
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
|
@ -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!");
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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();
|
||||
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();
|
||||
|
||||
OwningPtr<MemoryBuffer> File;
|
||||
failIfError(MemoryBuffer::getOpenFile(FD, Filename, File,
|
||||
Status.getSize(), false),
|
||||
Filename);
|
||||
|
||||
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';
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user