llvm.org GIT mirror llvm / 584fe2d
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 Rafael Espindola 6 years ago
11 changed file(s) with 100 addition(s) and 87 deletion(s). Raw diff Collapse all Expand all
3030 Binary(const Binary &other) LLVM_DELETED_FUNCTION;
3131
3232 unsigned int TypeID;
33 bool BufferOwned;
3334
3435 protected:
3536 MemoryBuffer *Data;
3637
37 Binary(unsigned int Type, MemoryBuffer *Source);
38 Binary(unsigned int Type, MemoryBuffer *Source, bool BufferOwned = true);
3839
3940 enum {
4041 ID_Archive,
319319 StringRef &Result) const;
320320
321321 public:
322 COFFObjectFile(MemoryBuffer *Object, error_code &ec);
322 COFFObjectFile(MemoryBuffer *Object, error_code &EC, bool BufferOwned = true);
323323 virtual symbol_iterator begin_symbols() const;
324324 virtual symbol_iterator end_symbols() const;
325325 virtual symbol_iterator begin_dynamic_symbols() const;
164164 bool isDyldELFObject;
165165
166166 public:
167 ELFObjectFile(MemoryBuffer *Object, error_code &ec);
167 ELFObjectFile(MemoryBuffer *Object, error_code &EC, bool BufferOwned = true);
168168
169169 const Elf_Sym *getSymbol(DataRefImpl Symb) const;
170170
812812 }
813813
814814 template
815 ELFObjectFile::ELFObjectFile(MemoryBuffer *Object, error_code &ec)
815 ELFObjectFile::ELFObjectFile(MemoryBuffer *Object, error_code &ec,
816 bool BufferOwned)
816817 : ObjectFile(getELFType(static_cast(ELFT::TargetEndianness) ==
817818 support::little,
818819 ELFT::Is64Bits),
819 Object),
820 Object, BufferOwned),
820821 EF(Object, ec) {}
821822
822823 template
5656 };
5757
5858 MachOObjectFile(MemoryBuffer *Object, bool IsLittleEndian, bool Is64Bits,
59 error_code &ec);
59 error_code &EC, bool BufferOwned = true);
6060
6161 virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const;
6262 virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const;
269269 ObjectFile(const ObjectFile &other) LLVM_DELETED_FUNCTION;
270270
271271 protected:
272 ObjectFile(unsigned int Type, MemoryBuffer *source);
272 ObjectFile(unsigned int Type, MemoryBuffer *Source, bool BufferOwned = true);
273273
274274 const uint8_t *base() const {
275275 return reinterpret_cast(Data->getBufferStart());
378378 /// @brief Create ObjectFile from path.
379379 static ErrorOr createObjectFile(StringRef ObjectPath);
380380 static ErrorOr
381 createObjectFile(MemoryBuffer *Object,
381 createObjectFile(MemoryBuffer *Object, bool BufferOwned = true,
382382 sys::fs::file_magic Type = sys::fs::file_magic::unknown);
383383
384384 static inline bool classof(const Binary *v) {
386386 }
387387
388388 public:
389 static ErrorOr createCOFFObjectFile(MemoryBuffer *Object);
390 static ErrorOr createELFObjectFile(MemoryBuffer *Object);
391 static ErrorOr createMachOObjectFile(MemoryBuffer *Object);
389 static ErrorOr createCOFFObjectFile(MemoryBuffer *Object,
390 bool BufferOwned = true);
391 static ErrorOr createELFObjectFile(MemoryBuffer *Object,
392 bool BufferOwned = true);
393 static ErrorOr createMachOObjectFile(MemoryBuffer *Object,
394 bool BufferOwned = true);
392395 };
393396
394397 // Inline function definitions.
2525 using namespace object;
2626
2727 Binary::~Binary() {
28 delete Data;
28 if (BufferOwned)
29 delete Data;
2930 }
3031
31 Binary::Binary(unsigned int Type, MemoryBuffer *Source)
32 : TypeID(Type)
33 , Data(Source) {}
32 Binary::Binary(unsigned int Type, MemoryBuffer *Source, bool BufferOwned)
33 : TypeID(Type), BufferOwned(BufferOwned), Data(Source) {}
3434
3535 StringRef Binary::getData() const {
3636 return Data->getBuffer();
462462 return object_error::success;
463463 }
464464
465 COFFObjectFile::COFFObjectFile(MemoryBuffer *Object, error_code &EC)
466 : ObjectFile(Binary::ID_COFF, Object), COFFHeader(0), PE32Header(0),
467 DataDirectory(0), SectionTable(0), SymbolTable(0), StringTable(0),
468 StringTableSize(0), ImportDirectory(0), NumberOfImportDirectory(0),
469 ExportDirectory(0) {
465 COFFObjectFile::COFFObjectFile(MemoryBuffer *Object, error_code &EC,
466 bool BufferOwned)
467 : ObjectFile(Binary::ID_COFF, Object, BufferOwned), COFFHeader(0),
468 PE32Header(0), DataDirectory(0), SectionTable(0), SymbolTable(0),
469 StringTable(0), StringTableSize(0), ImportDirectory(0),
470 NumberOfImportDirectory(0), ExportDirectory(0) {
470471 // Check that we at least have enough room for a header.
471472 if (!checkSize(Data, EC, sizeof(coff_file_header))) return;
472473
10141015 return object_error::success;
10151016 }
10161017
1017 ErrorOr ObjectFile::createCOFFObjectFile(MemoryBuffer *Object) {
1018 ErrorOr ObjectFile::createCOFFObjectFile(MemoryBuffer *Object,
1019 bool BufferOwned) {
10181020 error_code EC;
1019 OwningPtr Ret(new COFFObjectFile(Object, EC));
1021 OwningPtr Ret(new COFFObjectFile(Object, EC, BufferOwned));
10201022 if (EC)
10211023 return EC;
10221024 return Ret.take();
1616 namespace llvm {
1717 using namespace object;
1818
19 ErrorOr ObjectFile::createELFObjectFile(MemoryBuffer *Obj) {
19 ErrorOr ObjectFile::createELFObjectFile(MemoryBuffer *Obj,
20 bool BufferOwned) {
2021 std::pair Ident = getElfArchType(Obj);
2122 std::size_t MaxAlignment =
2223 1ULL << countTrailingZeros(uintptr_t(Obj->getBufferStart()));
2627 if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2LSB)
2728 #if !LLVM_IS_UNALIGNED_ACCESS_FAST
2829 if (MaxAlignment >= 4)
29 R.reset(new ELFObjectFile >(Obj, EC));
30 R.reset(new ELFObjectFile >(
31 Obj, EC, BufferOwned));
3032 else
3133 #endif
3234 if (MaxAlignment >= 2)
33 R.reset(new ELFObjectFile >(Obj, EC));
35 R.reset(new ELFObjectFile >(
36 Obj, EC, BufferOwned));
3437 else
3538 llvm_unreachable("Invalid alignment for ELF file!");
3639 else if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2MSB)
3740 #if !LLVM_IS_UNALIGNED_ACCESS_FAST
3841 if (MaxAlignment >= 4)
39 R.reset(new ELFObjectFile >(Obj, EC));
42 R.reset(new ELFObjectFile >(Obj, EC,
43 BufferOwned));
4044 else
4145 #endif
4246 if (MaxAlignment >= 2)
43 R.reset(new ELFObjectFile >(Obj, EC));
47 R.reset(new ELFObjectFile >(Obj, EC,
48 BufferOwned));
4449 else
4550 llvm_unreachable("Invalid alignment for ELF file!");
4651 else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2MSB)
4752 #if !LLVM_IS_UNALIGNED_ACCESS_FAST
4853 if (MaxAlignment >= 8)
49 R.reset(new ELFObjectFile >(Obj, EC));
54 R.reset(new ELFObjectFile >(Obj, EC,
55 BufferOwned));
5056 else
5157 #endif
5258 if (MaxAlignment >= 2)
53 R.reset(new ELFObjectFile >(Obj, EC));
59 R.reset(new ELFObjectFile >(Obj, EC,
60 BufferOwned));
5461 else
5562 llvm_unreachable("Invalid alignment for ELF file!");
5663 else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2LSB) {
5764 #if !LLVM_IS_UNALIGNED_ACCESS_FAST
5865 if (MaxAlignment >= 8)
59 R.reset(new ELFObjectFile >(Obj, EC));
66 R.reset(new ELFObjectFile >(
67 Obj, EC, BufferOwned));
6068 else
6169 #endif
6270 if (MaxAlignment >= 2)
63 R.reset(new ELFObjectFile >(Obj, EC));
71 R.reset(new ELFObjectFile >(
72 Obj, EC, BufferOwned));
6473 else
6574 llvm_unreachable("Invalid alignment for ELF file!");
6675 }
418418 return Sect.flags;
419419 }
420420
421 MachOObjectFile::MachOObjectFile(MemoryBuffer *Object,
422 bool IsLittleEndian, bool Is64bits,
423 error_code &ec)
424 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
421 MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, bool IsLittleEndian,
422 bool Is64bits, error_code &EC,
423 bool BufferOwned)
424 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object, BufferOwned),
425425 SymtabLoadCmd(NULL), DysymtabLoadCmd(NULL), DataInCodeLoadCmd(NULL) {
426426 uint32_t LoadCommandCount = this->getHeader().ncmds;
427427 MachO::LoadCommandType SegmentLoadType = is64Bit() ?
15811581 }
15821582 }
15831583
1584 ErrorOr ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) {
1584 ErrorOr ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer,
1585 bool BufferOwned) {
15851586 StringRef Magic = Buffer->getBuffer().slice(0, 4);
15861587 error_code EC;
15871588 OwningPtr Ret;
15881589 if (Magic == "\xFE\xED\xFA\xCE")
1589 Ret.reset(new MachOObjectFile(Buffer, false, false, EC));
1590 Ret.reset(new MachOObjectFile(Buffer, false, false, EC, BufferOwned));
15901591 else if (Magic == "\xCE\xFA\xED\xFE")
1591 Ret.reset(new MachOObjectFile(Buffer, true, false, EC));
1592 Ret.reset(new MachOObjectFile(Buffer, true, false, EC, BufferOwned));
15921593 else if (Magic == "\xFE\xED\xFA\xCF")
1593 Ret.reset(new MachOObjectFile(Buffer, false, true, EC));
1594 Ret.reset(new MachOObjectFile(Buffer, false, true, EC, BufferOwned));
15941595 else if (Magic == "\xCF\xFA\xED\xFE")
1595 Ret.reset(new MachOObjectFile(Buffer, true, true, EC));
1596 Ret.reset(new MachOObjectFile(Buffer, true, true, EC, BufferOwned));
15961597 else {
15971598 delete Buffer;
15981599 return object_error::parse_failed;
2222
2323 void ObjectFile::anchor() { }
2424
25 ObjectFile::ObjectFile(unsigned int Type, MemoryBuffer *source)
26 : Binary(Type, source) {
27 }
25 ObjectFile::ObjectFile(unsigned int Type, MemoryBuffer *Source,
26 bool BufferOwned)
27 : Binary(Type, Source, BufferOwned) {}
2828
2929 error_code ObjectFile::getSymbolAlignment(DataRefImpl DRI,
3030 uint32_t &Result) const {
3737 }
3838
3939 ErrorOr ObjectFile::createObjectFile(MemoryBuffer *Object,
40 bool BufferOwned,
4041 sys::fs::file_magic Type) {
41 OwningPtr ScopedObj(Object);
4242 if (Type == sys::fs::file_magic::unknown)
4343 Type = sys::fs::identify_magic(Object->getBuffer());
4444
4848 case sys::fs::file_magic::archive:
4949 case sys::fs::file_magic::macho_universal_binary:
5050 case sys::fs::file_magic::windows_resource:
51 if (BufferOwned)
52 delete Object;
5153 return object_error::invalid_file_type;
5254 case sys::fs::file_magic::elf_relocatable:
5355 case sys::fs::file_magic::elf_executable:
5456 case sys::fs::file_magic::elf_shared_object:
5557 case sys::fs::file_magic::elf_core:
56 return createELFObjectFile(ScopedObj.take());
58 return createELFObjectFile(Object, BufferOwned);
5759 case sys::fs::file_magic::macho_object:
5860 case sys::fs::file_magic::macho_executable:
5961 case sys::fs::file_magic::macho_fixed_virtual_memory_shared_lib:
6466 case sys::fs::file_magic::macho_bundle:
6567 case sys::fs::file_magic::macho_dynamically_linked_shared_lib_stub:
6668 case sys::fs::file_magic::macho_dsym_companion:
67 return createMachOObjectFile(ScopedObj.take());
69 return createMachOObjectFile(Object, BufferOwned);
6870 case sys::fs::file_magic::coff_object:
6971 case sys::fs::file_magic::coff_import_library:
7072 case sys::fs::file_magic::pecoff_executable:
71 return createCOFFObjectFile(ScopedObj.take());
73 return createCOFFObjectFile(Object, BufferOwned);
7274 }
7375 llvm_unreachable("Unexpected Object File Type");
7476 }
691691
692692 static void writeSymbolTable(
693693 raw_fd_ostream &Out, ArrayRef Members,
694 ArrayRef > Buffers,
694695 std::vector > &MemberOffsetRefs) {
695696 unsigned StartOffset = 0;
696697 unsigned MemberNum = 0;
699700 for (ArrayRef::iterator I = Members.begin(),
700701 E = Members.end();
701702 I != E; ++I, ++MemberNum) {
702 object::ObjectFile *Obj;
703 if (I->isNewMember()) {
704 const char *Filename = I->getNew();
705 int FD = I->getFD();
706 const sys::fs::file_status &Status = I->getStatus();
707
708 OwningPtr File;
709 failIfError(MemoryBuffer::getOpenFile(FD, Filename, File,
710 Status.getSize(), false),
711 Filename);
712
713 if (ErrorOr ObjOrErr =
714 object::ObjectFile::createObjectFile(File.take()))
715 Obj = ObjOrErr.get();
716 else
717 Obj = NULL;
718 } else {
719 object::Archive::child_iterator OldMember = I->getOld();
720 OwningPtr Binary;
721 error_code EC = OldMember->getAsBinary(Binary);
722 if (EC) { // FIXME: check only for "not an object file" errors.
723 Obj = NULL;
724 } else {
725 Obj = dyn_cast(Binary.get());
726 if (Obj)
727 Binary.take();
728 }
729 }
730 if (!Obj)
731 continue;
703 const OwningPtr &MemberBuffer = Buffers[MemberNum];
704 ErrorOr ObjOrErr =
705 object::ObjectFile::createObjectFile(MemberBuffer.get(), false);
706 if (!ObjOrErr)
707 continue; // FIXME: check only for "not an object file" errors.
708 object::ObjectFile *Obj = ObjOrErr.get();
709
732710 DeleteIt.push_back(Obj);
733711 if (!StartOffset) {
734712 printMemberHeader(Out, "", sys::TimeValue::now(), 0, 0, 0, 0);
799777
800778 std::vector > MemberOffsetRefs;
801779
780 std::vector > MemberBuffers;
781 MemberBuffers.resize(NewMembers.size());
782
783 for (unsigned I = 0, N = NewMembers.size(); I < N; ++I) {
784 OwningPtr &MemberBuffer = MemberBuffers[I];
785 NewArchiveIterator &Member = NewMembers[I];
786
787 if (Member.isNewMember()) {
788 const char *Filename = Member.getNew();
789 int FD = Member.getFD();
790 const sys::fs::file_status &Status = Member.getStatus();
791 failIfError(MemoryBuffer::getOpenFile(FD, Filename, MemberBuffer,
792 Status.getSize(), false),
793 Filename);
794
795 } else {
796 object::Archive::child_iterator OldMember = Member.getOld();
797 failIfError(OldMember->getMemoryBuffer(MemberBuffer));
798 }
799 }
800
802801 if (Symtab) {
803 writeSymbolTable(Out, NewMembers, MemberOffsetRefs);
802 writeSymbolTable(Out, NewMembers, MemberBuffers, MemberOffsetRefs);
804803 }
805804
806805 std::vector StringMapIndexes;
824823 }
825824 Out.seek(Pos);
826825
826 const OwningPtr &File = MemberBuffers[MemberNum];
827827 if (I->isNewMember()) {
828828 const char *FileName = I->getNew();
829 int FD = I->getFD();
830829 const sys::fs::file_status &Status = I->getStatus();
831
832 OwningPtr File;
833 failIfError(MemoryBuffer::getOpenFile(FD, FileName, File,
834 Status.getSize(), false),
835 FileName);
836830
837831 StringRef Name = sys::path::filename(FileName);
838832 if (Name.size() < 16)
844838 Status.getLastModificationTime(), Status.getUser(),
845839 Status.getGroup(), Status.permissions(),
846840 Status.getSize());
847 Out << File->getBuffer();
848841 } else {
849842 object::Archive::child_iterator OldMember = I->getOld();
850843 StringRef Name = I->getName();
858851 OldMember->getLastModified(), OldMember->getUID(),
859852 OldMember->getGID(), OldMember->getAccessMode(),
860853 OldMember->getSize());
861 Out << OldMember->getBuffer();
862 }
854 }
855
856 Out << File->getBuffer();
863857
864858 if (Out.tell() % 2)
865859 Out << '\n';