Make ObjectFile and BitcodeReader always own the MemoryBuffer.

This allows us to just use a std::unique_ptr to store the pointer to the buffer.
The flip side is that they have to support releasing the buffer back to the
caller.

Overall this looks like a more efficient and less brittle api.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@211542 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Rafael Espindola
2014-06-23 21:53:12 +00:00
parent 7e7e89f178
commit 1f659329b6
23 changed files with 117 additions and 154 deletions

View File

@@ -181,7 +181,12 @@ Archive::Child::getAsBinary(LLVMContext *Context) const {
ErrorOr<std::unique_ptr<MemoryBuffer>> BuffOrErr = getMemoryBuffer();
if (std::error_code EC = BuffOrErr.getError())
return EC;
return createBinary(BuffOrErr.get().release(), Context);
std::unique_ptr<MemoryBuffer> Buff(BuffOrErr.get().release());
ErrorOr<std::unique_ptr<Binary>> Ret = createBinary(Buff.get(), Context);
if (!Ret.getError())
Buff.release();
return Ret;
}
ErrorOr<Archive*> Archive::create(MemoryBuffer *Source) {

View File

@@ -25,13 +25,10 @@
using namespace llvm;
using namespace object;
Binary::~Binary() {
if (BufferOwned)
delete Data;
}
Binary::~Binary() {}
Binary::Binary(unsigned int Type, MemoryBuffer *Source, bool BufferOwned)
: TypeID(Type), BufferOwned(BufferOwned), Data(Source) {}
Binary::Binary(unsigned int Type, MemoryBuffer *Source)
: TypeID(Type), Data(Source) {}
StringRef Binary::getData() const {
return Data->getBuffer();
@@ -41,14 +38,13 @@ StringRef Binary::getFileName() const {
return Data->getBufferIdentifier();
}
ErrorOr<Binary *> object::createBinary(MemoryBuffer *Source,
ErrorOr<Binary *> object::createBinary(MemoryBuffer *Buffer,
LLVMContext *Context) {
std::unique_ptr<MemoryBuffer> scopedSource(Source);
sys::fs::file_magic Type = sys::fs::identify_magic(Source->getBuffer());
sys::fs::file_magic Type = sys::fs::identify_magic(Buffer->getBuffer());
switch (Type) {
case sys::fs::file_magic::archive:
return Archive::create(scopedSource.release());
return Archive::create(Buffer);
case sys::fs::file_magic::elf_relocatable:
case sys::fs::file_magic::elf_executable:
case sys::fs::file_magic::elf_shared_object:
@@ -67,10 +63,9 @@ ErrorOr<Binary *> object::createBinary(MemoryBuffer *Source,
case sys::fs::file_magic::coff_import_library:
case sys::fs::file_magic::pecoff_executable:
case sys::fs::file_magic::bitcode:
return ObjectFile::createSymbolicFile(scopedSource.release(), true, Type,
Context);
return ObjectFile::createSymbolicFile(Buffer, Type, Context);
case sys::fs::file_magic::macho_universal_binary:
return MachOUniversalBinary::create(scopedSource.release());
return MachOUniversalBinary::create(Buffer);
case sys::fs::file_magic::unknown:
case sys::fs::file_magic::windows_resource:
// Unrecognized object file format.

View File

@@ -31,9 +31,9 @@ using support::ulittle32_t;
using support::little16_t;
// Returns false if size is greater than the buffer size. And sets ec.
static bool checkSize(const MemoryBuffer *M, std::error_code &EC,
static bool checkSize(const MemoryBuffer &M, std::error_code &EC,
uint64_t Size) {
if (M->getBufferSize() < Size) {
if (M.getBufferSize() < Size) {
EC = object_error::unexpected_eof;
return false;
}
@@ -43,13 +43,12 @@ static bool checkSize(const MemoryBuffer *M, std::error_code &EC,
// Sets Obj unless any bytes in [addr, addr + size) fall outsize of m.
// Returns unexpected_eof if error.
template <typename T>
static std::error_code getObject(const T *&Obj, const MemoryBuffer *M,
static std::error_code getObject(const T *&Obj, const MemoryBuffer &M,
const uint8_t *Ptr,
const size_t Size = sizeof(T)) {
uintptr_t Addr = uintptr_t(Ptr);
if (Addr + Size < Addr ||
Addr + Size < Size ||
Addr + Size > uintptr_t(M->getBufferEnd())) {
if (Addr + Size < Addr || Addr + Size < Size ||
Addr + Size > uintptr_t(M.getBufferEnd())) {
return object_error::unexpected_eof;
}
Obj = reinterpret_cast<const T *>(Addr);
@@ -398,7 +397,7 @@ relocation_iterator COFFObjectFile::section_rel_end(DataRefImpl Ref) const {
// Initialize the pointer to the symbol table.
std::error_code COFFObjectFile::initSymbolTablePtr() {
if (std::error_code EC = getObject(
SymbolTable, Data, base() + COFFHeader->PointerToSymbolTable,
SymbolTable, *Data, base() + COFFHeader->PointerToSymbolTable,
COFFHeader->NumberOfSymbols * sizeof(coff_symbol)))
return EC;
@@ -409,11 +408,12 @@ std::error_code COFFObjectFile::initSymbolTablePtr() {
base() + COFFHeader->PointerToSymbolTable +
COFFHeader->NumberOfSymbols * sizeof(coff_symbol);
const ulittle32_t *StringTableSizePtr;
if (std::error_code EC = getObject(StringTableSizePtr, Data, StringTableAddr))
if (std::error_code EC =
getObject(StringTableSizePtr, *Data, StringTableAddr))
return EC;
StringTableSize = *StringTableSizePtr;
if (std::error_code EC =
getObject(StringTable, Data, StringTableAddr, StringTableSize))
getObject(StringTable, *Data, StringTableAddr, StringTableSize))
return EC;
// Treat table sizes < 4 as empty because contrary to the PECOFF spec, some
@@ -511,15 +511,15 @@ std::error_code COFFObjectFile::initExportTablePtr() {
return object_error::success;
}
COFFObjectFile::COFFObjectFile(MemoryBuffer *Object, std::error_code &EC,
bool BufferOwned)
: ObjectFile(Binary::ID_COFF, Object, BufferOwned), COFFHeader(nullptr),
COFFObjectFile::COFFObjectFile(MemoryBuffer *Object, std::error_code &EC)
: ObjectFile(Binary::ID_COFF, Object), COFFHeader(nullptr),
PE32Header(nullptr), PE32PlusHeader(nullptr), DataDirectory(nullptr),
SectionTable(nullptr), SymbolTable(nullptr), StringTable(nullptr),
StringTableSize(0), ImportDirectory(nullptr), NumberOfImportDirectory(0),
ExportDirectory(nullptr) {
// Check that we at least have enough room for a header.
if (!checkSize(Data, EC, sizeof(coff_file_header))) return;
if (!checkSize(*Data, EC, sizeof(coff_file_header)))
return;
// The current location in the file where we are looking at.
uint64_t CurPtr = 0;
@@ -532,7 +532,8 @@ COFFObjectFile::COFFObjectFile(MemoryBuffer *Object, std::error_code &EC,
if (base()[0] == 0x4d && base()[1] == 0x5a) {
// PE/COFF, seek through MS-DOS compatibility stub and 4-byte
// PE signature to find 'normal' COFF header.
if (!checkSize(Data, EC, 0x3c + 8)) return;
if (!checkSize(*Data, EC, 0x3c + 8))
return;
CurPtr = *reinterpret_cast<const ulittle16_t *>(base() + 0x3c);
// Check the PE magic bytes. ("PE\0\0")
if (std::memcmp(base() + CurPtr, "PE\0\0", 4) != 0) {
@@ -543,13 +544,13 @@ COFFObjectFile::COFFObjectFile(MemoryBuffer *Object, std::error_code &EC,
HasPEHeader = true;
}
if ((EC = getObject(COFFHeader, Data, base() + CurPtr)))
if ((EC = getObject(COFFHeader, *Data, base() + CurPtr)))
return;
CurPtr += sizeof(coff_file_header);
if (HasPEHeader) {
const pe32_header *Header;
if ((EC = getObject(Header, Data, base() + CurPtr)))
if ((EC = getObject(Header, *Data, base() + CurPtr)))
return;
const uint8_t *DataDirAddr;
@@ -567,7 +568,7 @@ COFFObjectFile::COFFObjectFile(MemoryBuffer *Object, std::error_code &EC,
EC = object_error::parse_failed;
return;
}
if ((EC = getObject(DataDirectory, Data, DataDirAddr, DataDirSize)))
if ((EC = getObject(DataDirectory, *Data, DataDirAddr, DataDirSize)))
return;
CurPtr += COFFHeader->SizeOfOptionalHeader;
}
@@ -575,7 +576,7 @@ COFFObjectFile::COFFObjectFile(MemoryBuffer *Object, std::error_code &EC,
if (COFFHeader->isImportLibrary())
return;
if ((EC = getObject(SectionTable, Data, base() + CurPtr,
if ((EC = getObject(SectionTable, *Data, base() + CurPtr,
COFFHeader->NumberOfSections * sizeof(coff_section))))
return;
@@ -1110,11 +1111,9 @@ ExportDirectoryEntryRef::getSymbolName(StringRef &Result) const {
return object_error::success;
}
ErrorOr<ObjectFile *> ObjectFile::createCOFFObjectFile(MemoryBuffer *Object,
bool BufferOwned) {
ErrorOr<ObjectFile *> ObjectFile::createCOFFObjectFile(MemoryBuffer *Object) {
std::error_code EC;
std::unique_ptr<COFFObjectFile> Ret(
new COFFObjectFile(Object, EC, BufferOwned));
std::unique_ptr<COFFObjectFile> Ret(new COFFObjectFile(Object, EC));
if (EC)
return EC;
return Ret.release();

View File

@@ -17,8 +17,7 @@
namespace llvm {
using namespace object;
static ErrorOr<ObjectFile *> createELFObjectFileAux(MemoryBuffer *Obj,
bool BufferOwned) {
ErrorOr<ObjectFile *> ObjectFile::createELFObjectFile(MemoryBuffer *Obj) {
std::pair<unsigned char, unsigned char> Ident = getElfArchType(Obj);
std::size_t MaxAlignment =
1ULL << countTrailingZeros(uintptr_t(Obj->getBufferStart()));
@@ -28,49 +27,41 @@ static ErrorOr<ObjectFile *> createELFObjectFileAux(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, BufferOwned));
R.reset(new ELFObjectFile<ELFType<support::little, 4, false>>(Obj, EC));
else
#endif
if (MaxAlignment >= 2)
R.reset(new ELFObjectFile<ELFType<support::little, 2, false> >(
Obj, EC, BufferOwned));
R.reset(new ELFObjectFile<ELFType<support::little, 2, false>>(Obj, EC));
else
return object_error::parse_failed;
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,
BufferOwned));
R.reset(new ELFObjectFile<ELFType<support::big, 4, false>>(Obj, EC));
else
#endif
if (MaxAlignment >= 2)
R.reset(new ELFObjectFile<ELFType<support::big, 2, false> >(Obj, EC,
BufferOwned));
R.reset(new ELFObjectFile<ELFType<support::big, 2, false>>(Obj, EC));
else
return object_error::parse_failed;
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,
BufferOwned));
R.reset(new ELFObjectFile<ELFType<support::big, 8, true>>(Obj, EC));
else
#endif
if (MaxAlignment >= 2)
R.reset(new ELFObjectFile<ELFType<support::big, 2, true> >(Obj, EC,
BufferOwned));
R.reset(new ELFObjectFile<ELFType<support::big, 2, true>>(Obj, EC));
else
return object_error::parse_failed;
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, BufferOwned));
R.reset(new ELFObjectFile<ELFType<support::little, 8, true>>(Obj, EC));
else
#endif
if (MaxAlignment >= 2)
R.reset(new ELFObjectFile<ELFType<support::little, 2, true> >(
Obj, EC, BufferOwned));
R.reset(new ELFObjectFile<ELFType<support::little, 2, true>>(Obj, EC));
else
return object_error::parse_failed;
}
@@ -82,12 +73,4 @@ static ErrorOr<ObjectFile *> createELFObjectFileAux(MemoryBuffer *Obj,
return R.release();
}
ErrorOr<ObjectFile *> ObjectFile::createELFObjectFile(MemoryBuffer *Obj,
bool BufferOwned) {
ErrorOr<ObjectFile *> Ret = createELFObjectFileAux(Obj, BufferOwned);
if (BufferOwned && Ret.getError())
delete Obj;
return Ret;
}
} // end namespace llvm

View File

@@ -13,6 +13,7 @@
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/GVMaterializer.h"
#include "llvm/IR/Mangler.h"
#include "llvm/IR/Module.h"
#include "llvm/Object/IRObjectFile.h"
@@ -21,10 +22,9 @@ using namespace llvm;
using namespace object;
IRObjectFile::IRObjectFile(MemoryBuffer *Object, std::error_code &EC,
LLVMContext &Context, bool BufferOwned)
: SymbolicFile(Binary::ID_IR, Object, BufferOwned) {
ErrorOr<Module *> MOrErr =
getLazyBitcodeModule(Object, Context, /*BufferOwned*/ false);
LLVMContext &Context)
: SymbolicFile(Binary::ID_IR, Object) {
ErrorOr<Module *> MOrErr = getLazyBitcodeModule(Object, Context);
if ((EC = MOrErr.getError()))
return;
@@ -38,6 +38,8 @@ IRObjectFile::IRObjectFile(MemoryBuffer *Object, std::error_code &EC,
Mang.reset(new Mangler(DL));
}
IRObjectFile::~IRObjectFile() { M->getMaterializer()->releaseBuffer(); }
static const GlobalValue &getGV(DataRefImpl &Symb) {
return *reinterpret_cast<GlobalValue*>(Symb.p & ~uintptr_t(3));
}
@@ -151,11 +153,11 @@ basic_symbol_iterator IRObjectFile::symbol_end_impl() const {
return basic_symbol_iterator(BasicSymbolRef(Ret, this));
}
ErrorOr<SymbolicFile *> llvm::object::SymbolicFile::createIRObjectFile(
MemoryBuffer *Object, LLVMContext &Context, bool BufferOwned) {
ErrorOr<SymbolicFile *>
llvm::object::SymbolicFile::createIRObjectFile(MemoryBuffer *Object,
LLVMContext &Context) {
std::error_code EC;
std::unique_ptr<IRObjectFile> Ret(
new IRObjectFile(Object, EC, Context, BufferOwned));
std::unique_ptr<IRObjectFile> Ret(new IRObjectFile(Object, EC, Context));
if (EC)
return EC;
return Ret.release();

View File

@@ -423,9 +423,8 @@ static uint32_t getSectionFlags(const MachOObjectFile *O,
}
MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, bool IsLittleEndian,
bool Is64bits, std::error_code &EC,
bool BufferOwned)
: ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object, BufferOwned),
bool Is64bits, std::error_code &EC)
: ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr),
DataInCodeLoadCmd(nullptr) {
uint32_t LoadCommandCount = this->getHeader().ncmds;
@@ -1812,19 +1811,18 @@ void MachOObjectFile::ReadULEB128s(uint64_t Index,
}
}
ErrorOr<ObjectFile *> ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer,
bool BufferOwned) {
ErrorOr<ObjectFile *> ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) {
StringRef Magic = Buffer->getBuffer().slice(0, 4);
std::error_code EC;
std::unique_ptr<MachOObjectFile> Ret;
if (Magic == "\xFE\xED\xFA\xCE")
Ret.reset(new MachOObjectFile(Buffer, false, false, EC, BufferOwned));
Ret.reset(new MachOObjectFile(Buffer, false, false, EC));
else if (Magic == "\xCE\xFA\xED\xFE")
Ret.reset(new MachOObjectFile(Buffer, true, false, EC, BufferOwned));
Ret.reset(new MachOObjectFile(Buffer, true, false, EC));
else if (Magic == "\xFE\xED\xFA\xCF")
Ret.reset(new MachOObjectFile(Buffer, false, true, EC, BufferOwned));
Ret.reset(new MachOObjectFile(Buffer, false, true, EC));
else if (Magic == "\xCF\xFA\xED\xFE")
Ret.reset(new MachOObjectFile(Buffer, true, true, EC, BufferOwned));
Ret.reset(new MachOObjectFile(Buffer, true, true, EC));
else {
delete Buffer;
return object_error::parse_failed;

View File

@@ -23,9 +23,8 @@ using namespace object;
void ObjectFile::anchor() { }
ObjectFile::ObjectFile(unsigned int Type, MemoryBuffer *Source,
bool BufferOwned)
: SymbolicFile(Type, Source, BufferOwned) {}
ObjectFile::ObjectFile(unsigned int Type, MemoryBuffer *Source)
: SymbolicFile(Type, Source) {}
std::error_code ObjectFile::printSymbolName(raw_ostream &OS,
DataRefImpl Symb) const {
@@ -47,7 +46,6 @@ section_iterator ObjectFile::getRelocatedSection(DataRefImpl Sec) const {
}
ErrorOr<ObjectFile *> ObjectFile::createObjectFile(MemoryBuffer *Object,
bool BufferOwned,
sys::fs::file_magic Type) {
if (Type == sys::fs::file_magic::unknown)
Type = sys::fs::identify_magic(Object->getBuffer());
@@ -58,14 +56,12 @@ 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(Object, BufferOwned);
return createELFObjectFile(Object);
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:
@@ -76,11 +72,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(Object, BufferOwned);
return createMachOObjectFile(Object);
case sys::fs::file_magic::coff_object:
case sys::fs::file_magic::coff_import_library:
case sys::fs::file_magic::pecoff_executable:
return createCOFFObjectFile(Object, BufferOwned);
return createCOFFObjectFile(Object);
}
llvm_unreachable("Unexpected Object File Type");
}

View File

@@ -19,15 +19,13 @@
using namespace llvm;
using namespace object;
SymbolicFile::SymbolicFile(unsigned int Type, MemoryBuffer *Source,
bool BufferOwned)
: Binary(Type, Source, BufferOwned) {}
SymbolicFile::SymbolicFile(unsigned int Type, MemoryBuffer *Source)
: Binary(Type, Source) {}
SymbolicFile::~SymbolicFile() {}
ErrorOr<SymbolicFile *>
SymbolicFile::createSymbolicFile(MemoryBuffer *Object, bool BufferOwned,
sys::fs::file_magic Type,
SymbolicFile::createSymbolicFile(MemoryBuffer *Object, sys::fs::file_magic Type,
LLVMContext *Context) {
if (Type == sys::fs::file_magic::unknown)
Type = sys::fs::identify_magic(Object->getBuffer());
@@ -35,14 +33,12 @@ SymbolicFile::createSymbolicFile(MemoryBuffer *Object, bool BufferOwned,
switch (Type) {
case sys::fs::file_magic::bitcode:
if (Context)
return IRObjectFile::createIRObjectFile(Object, *Context, BufferOwned);
return IRObjectFile::createIRObjectFile(Object, *Context);
// Fallthrough
case sys::fs::file_magic::unknown:
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:
@@ -61,7 +57,7 @@ SymbolicFile::createSymbolicFile(MemoryBuffer *Object, bool BufferOwned,
case sys::fs::file_magic::coff_object:
case sys::fs::file_magic::coff_import_library:
case sys::fs::file_magic::pecoff_executable:
return ObjectFile::createObjectFile(Object, BufferOwned, Type);
return ObjectFile::createObjectFile(Object, Type);
}
llvm_unreachable("Unexpected Binary File Type");
}