diff options
author | Alexey Lapshin <a.v.lapshin@mail.ru> | 2020-10-24 17:35:55 +0300 |
---|---|---|
committer | Alexey Lapshin <a.v.lapshin@mail.ru> | 2021-03-10 23:50:04 +0300 |
commit | 4f16e177e104eb80589311dc3cc1b5355a7e41bb (patch) | |
tree | 06e72462e979bc7c50f01b60401bfe81db406d74 /llvm/tools/llvm-objcopy/ELF/Object.cpp | |
parent | 619c1505f9445501551ffedd85cf361a4c5917f0 (diff) | |
download | llvm-4f16e177e104eb80589311dc3cc1b5355a7e41bb.zip llvm-4f16e177e104eb80589311dc3cc1b5355a7e41bb.tar.gz llvm-4f16e177e104eb80589311dc3cc1b5355a7e41bb.tar.bz2 |
[llvm-objcopy][NFC] replace class Buffer/MemBuffer/FileBuffer with streams.
During D88827 it was requested to remove the local implementation
of Memory/File Buffers:
// TODO: refactor the buffer classes in LLVM to enable us to use them here
// directly.
This patch uses raw_ostream instead of Buffers. Generally, using streams
could allow us to reduce memory usages. No need to load all data into the
memory - the data could be streamed through a smaller buffer.
Thus, this patch uses raw_ostream as an interface for output data:
Error executeObjcopyOnBinary(CopyConfig &Config,
object::Binary &In,
raw_ostream &Out);
Note 1. This patch does not change the implementation of Writers
so that data would be directly stored into raw_ostream.
This is assumed to be done later.
Note 2. It would be better if Writers would be implemented in a such way
that data could be streamed without seeking/updating. If that would be
inconvenient then raw_ostream could be replaced with raw_pwrite_stream
to have a possibility to seek back and update file headers.
This is assumed to be done later if necessary.
Note 3. Current FileOutputBuffer allows using a memory-mapped file.
The raw_fd_ostream (which could be used if data should be stored in the file)
does not allow us to use a memory-mapped file. Memory map functionality
could be implemented for raw_fd_ostream:
It is possible to add resize() method into raw_ostream.
class raw_ostream {
void resize(uint64_t size);
}
That method, implemented for raw_fd_ostream, could create a memory-mapped file.
The streamed data would be written into that memory file then.
Thus we would be able to use memory-mapped files with raw_fd_ostream.
This is assumed to be done later if necessary.
Differential Revision: https://reviews.llvm.org/D91028
Diffstat (limited to 'llvm/tools/llvm-objcopy/ELF/Object.cpp')
-rw-r--r-- | llvm/tools/llvm-objcopy/ELF/Object.cpp | 95 |
1 files changed, 65 insertions, 30 deletions
diff --git a/llvm/tools/llvm-objcopy/ELF/Object.cpp b/llvm/tools/llvm-objcopy/ELF/Object.cpp index 7fa9621e..a8bd135 100644 --- a/llvm/tools/llvm-objcopy/ELF/Object.cpp +++ b/llvm/tools/llvm-objcopy/ELF/Object.cpp @@ -37,8 +37,8 @@ using namespace object; using namespace ELF; template <class ELFT> void ELFWriter<ELFT>::writePhdr(const Segment &Seg) { - uint8_t *B = Buf.getBufferStart() + Obj.ProgramHdrSegment.Offset + - Seg.Index * sizeof(Elf_Phdr); + uint8_t *B = reinterpret_cast<uint8_t *>(Buf->getBufferStart()) + + Obj.ProgramHdrSegment.Offset + Seg.Index * sizeof(Elf_Phdr); Elf_Phdr &Phdr = *reinterpret_cast<Elf_Phdr *>(B); Phdr.p_type = Seg.Type; Phdr.p_flags = Seg.Flags; @@ -67,7 +67,8 @@ void SectionBase::replaceSectionReferences( void SectionBase::onRemove() {} template <class ELFT> void ELFWriter<ELFT>::writeShdr(const SectionBase &Sec) { - uint8_t *B = Buf.getBufferStart() + Sec.HeaderOffset; + uint8_t *B = + reinterpret_cast<uint8_t *>(Buf->getBufferStart()) + Sec.HeaderOffset; Elf_Shdr &Shdr = *reinterpret_cast<Elf_Shdr *>(B); Shdr.sh_name = Sec.NameIndex; Shdr.sh_type = Sec.Type; @@ -474,7 +475,7 @@ Error ELFSectionWriter<ELFT>::visit(const DecompressedSection &Sec) { return createStringError(errc::invalid_argument, "'" + Sec.Name + "': " + toString(std::move(Err))); - uint8_t *Buf = Out.getBufferStart() + Sec.Offset; + uint8_t *Buf = reinterpret_cast<uint8_t *>(Out.getBufferStart()) + Sec.Offset; std::copy(DecompressedContent.begin(), DecompressedContent.end(), Buf); return Error::success(); @@ -519,7 +520,7 @@ Error BinarySectionWriter::visit(const CompressedSection &Sec) { template <class ELFT> Error ELFSectionWriter<ELFT>::visit(const CompressedSection &Sec) { - uint8_t *Buf = Out.getBufferStart() + Sec.Offset; + uint8_t *Buf = reinterpret_cast<uint8_t *>(Out.getBufferStart()) + Sec.Offset; if (Sec.CompressionType == DebugCompressionType::None) { std::copy(Sec.OriginalData.begin(), Sec.OriginalData.end(), Buf); return Error::success(); @@ -624,7 +625,8 @@ void StringTableSection::prepareForLayout() { } Error SectionWriter::visit(const StringTableSection &Sec) { - Sec.StrTabBuilder.write(Out.getBufferStart() + Sec.Offset); + Sec.StrTabBuilder.write(reinterpret_cast<uint8_t *>(Out.getBufferStart()) + + Sec.Offset); return Error::success(); } @@ -638,7 +640,7 @@ Error StringTableSection::accept(MutableSectionVisitor &Visitor) { template <class ELFT> Error ELFSectionWriter<ELFT>::visit(const SectionIndexSection &Sec) { - uint8_t *Buf = Out.getBufferStart() + Sec.Offset; + uint8_t *Buf = reinterpret_cast<uint8_t *>(Out.getBufferStart()) + Sec.Offset; llvm::copy(Sec.Indexes, reinterpret_cast<Elf_Word *>(Buf)); return Error::success(); } @@ -979,7 +981,7 @@ static void writeRel(const RelRange &Relocations, T *Buf) { template <class ELFT> Error ELFSectionWriter<ELFT>::visit(const RelocationSection &Sec) { - uint8_t *Buf = Out.getBufferStart() + Sec.Offset; + uint8_t *Buf = reinterpret_cast<uint8_t *>(Out.getBufferStart()) + Sec.Offset; if (Sec.Type == SHT_REL) writeRel(Sec.Relocations, reinterpret_cast<Elf_Rel *>(Buf)); else @@ -1160,7 +1162,8 @@ GnuDebugLinkSection::GnuDebugLinkSection(StringRef File, template <class ELFT> Error ELFSectionWriter<ELFT>::visit(const GnuDebugLinkSection &Sec) { - unsigned char *Buf = Out.getBufferStart() + Sec.Offset; + unsigned char *Buf = + reinterpret_cast<uint8_t *>(Out.getBufferStart()) + Sec.Offset; Elf_Word *CRC = reinterpret_cast<Elf_Word *>(Buf + Sec.Size - sizeof(Elf_Word)); *CRC = Sec.CRC32; @@ -1972,7 +1975,7 @@ Expected<std::unique_ptr<Object>> ELFReader::create(bool EnsureSymtab) const { } template <class ELFT> void ELFWriter<ELFT>::writeEhdr() { - Elf_Ehdr &Ehdr = *reinterpret_cast<Elf_Ehdr *>(Buf.getBufferStart()); + Elf_Ehdr &Ehdr = *reinterpret_cast<Elf_Ehdr *>(Buf->getBufferStart()); std::fill(Ehdr.e_ident, Ehdr.e_ident + 16, 0); Ehdr.e_ident[EI_MAG0] = 0x7f; Ehdr.e_ident[EI_MAG1] = 'E'; @@ -2037,7 +2040,7 @@ template <class ELFT> void ELFWriter<ELFT>::writeShdrs() { // This reference serves to write the dummy section header at the begining // of the file. It is not used for anything else Elf_Shdr &Shdr = - *reinterpret_cast<Elf_Shdr *>(Buf.getBufferStart() + Obj.SHOff); + *reinterpret_cast<Elf_Shdr *>(Buf->getBufferStart() + Obj.SHOff); Shdr.sh_name = 0; Shdr.sh_type = SHT_NULL; Shdr.sh_flags = 0; @@ -2077,7 +2080,7 @@ template <class ELFT> Error ELFWriter<ELFT>::writeSectionData() { template <class ELFT> void ELFWriter<ELFT>::writeSegmentData() { for (Segment &Seg : Obj.segments()) { size_t Size = std::min<size_t>(Seg.FileSize, Seg.getContents().size()); - std::memcpy(Buf.getBufferStart() + Seg.Offset, Seg.getContents().data(), + std::memcpy(Buf->getBufferStart() + Seg.Offset, Seg.getContents().data(), Size); } @@ -2088,12 +2091,12 @@ template <class ELFT> void ELFWriter<ELFT>::writeSegmentData() { continue; uint64_t Offset = Sec.OriginalOffset - Parent->OriginalOffset + Parent->Offset; - std::memset(Buf.getBufferStart() + Offset, 0, Sec.Size); + std::memset(Buf->getBufferStart() + Offset, 0, Sec.Size); } } template <class ELFT> -ELFWriter<ELFT>::ELFWriter(Object &Obj, Buffer &Buf, bool WSH, +ELFWriter<ELFT>::ELFWriter(Object &Obj, raw_ostream &Buf, bool WSH, bool OnlyKeepDebug) : Writer(Obj, Buf), WriteSectionHeaders(WSH && Obj.HadShdrs), OnlyKeepDebug(OnlyKeepDebug) {} @@ -2410,7 +2413,11 @@ template <class ELFT> Error ELFWriter<ELFT>::write() { return E; if (WriteSectionHeaders) writeShdrs(); - return Buf.commit(); + + // TODO: Implement direct writing to the output stream (without intermediate + // memory buffer Buf). + Out.write(Buf->getBufferStart(), Buf->getBufferSize()); + return Error::success(); } static Error removeUnneededSections(Object &Obj) { @@ -2532,9 +2539,14 @@ template <class ELFT> Error ELFWriter<ELFT>::finalize() { Sec.finalize(); } - if (Error E = Buf.allocate(totalSize())) - return E; - SecWriter = std::make_unique<ELFSectionWriter<ELFT>>(Buf); + size_t TotalSize = totalSize(); + Buf = WritableMemoryBuffer::getNewMemBuffer(TotalSize); + if (!Buf) + return createStringError(errc::not_enough_memory, + "failed to allocate memory buffer of " + + Twine::utohexstr(TotalSize) + " bytes"); + + SecWriter = std::make_unique<ELFSectionWriter<ELFT>>(*Buf); return Error::success(); } @@ -2543,7 +2555,10 @@ Error BinaryWriter::write() { if (Error Err = Sec.accept(*SecWriter)) return Err; - return Buf.commit(); + // TODO: Implement direct writing to the output stream (without intermediate + // memory buffer Buf). + Out.write(Buf->getBufferStart(), Buf->getBufferSize()); + return Error::success(); } Error BinaryWriter::finalize() { @@ -2571,9 +2586,12 @@ Error BinaryWriter::finalize() { TotalSize = std::max(TotalSize, Sec.Offset + Sec.Size); } - if (Error E = Buf.allocate(TotalSize)) - return E; - SecWriter = std::make_unique<BinarySectionWriter>(Buf); + Buf = WritableMemoryBuffer::getNewMemBuffer(TotalSize); + if (!Buf) + return createStringError(errc::not_enough_memory, + "failed to allocate memory buffer of " + + Twine::utohexstr(TotalSize) + " bytes"); + SecWriter = std::make_unique<BinarySectionWriter>(*Buf); return Error::success(); } @@ -2611,7 +2629,7 @@ uint64_t IHexWriter::writeEndOfFileRecord(uint8_t *Buf) { } Error IHexWriter::write() { - IHexSectionWriter Writer(Buf); + IHexSectionWriter Writer(*Buf); // Write sections. for (const SectionBase *Sec : Sections) if (Error Err = Sec->accept(Writer)) @@ -2619,11 +2637,17 @@ Error IHexWriter::write() { uint64_t Offset = Writer.getBufferOffset(); // Write entry point address. - Offset += writeEntryPointRecord(Buf.getBufferStart() + Offset); + Offset += writeEntryPointRecord( + reinterpret_cast<uint8_t *>(Buf->getBufferStart()) + Offset); // Write EOF. - Offset += writeEndOfFileRecord(Buf.getBufferStart() + Offset); + Offset += writeEndOfFileRecord( + reinterpret_cast<uint8_t *>(Buf->getBufferStart()) + Offset); assert(Offset == TotalSize); - return Buf.commit(); + + // TODO: Implement direct writing to the output stream (without intermediate + // memory buffer Buf). + Out.write(Buf->getBufferStart(), Buf->getBufferSize()); + return Error::success(); } Error IHexWriter::checkSection(const SectionBase &Sec) { @@ -2648,7 +2672,7 @@ Error IHexWriter::finalize() { // We can't write 64-bit addresses. if (addressOverflows32bit(Obj.Entry)) return createStringError(errc::invalid_argument, - "Entry point address 0x%llx overflows 32 bits.", + "Entry point address 0x%llx overflows 32 bits", Obj.Entry); // If any section we're to write has segment then we @@ -2667,7 +2691,13 @@ Error IHexWriter::finalize() { Sections.insert(&Sec); } - IHexSectionWriterBase LengthCalc(Buf); + std::unique_ptr<WritableMemoryBuffer> EmptyBuffer = + WritableMemoryBuffer::getNewMemBuffer(0); + if (!EmptyBuffer) + return createStringError(errc::not_enough_memory, + "failed to allocate memory buffer of 0 bytes"); + + IHexSectionWriterBase LengthCalc(*EmptyBuffer); for (const SectionBase *Sec : Sections) if (Error Err = Sec->accept(LengthCalc)) return Err; @@ -2677,8 +2707,13 @@ Error IHexWriter::finalize() { TotalSize = LengthCalc.getBufferOffset() + (Obj.Entry ? IHexRecord::getLineLength(4) : 0) + IHexRecord::getLineLength(0); - if (Error E = Buf.allocate(TotalSize)) - return E; + + Buf = WritableMemoryBuffer::getNewMemBuffer(TotalSize); + if (!Buf) + return createStringError(errc::not_enough_memory, + "failed to allocate memory buffer of " + + Twine::utohexstr(TotalSize) + " bytes"); + return Error::success(); } |