aboutsummaryrefslogtreecommitdiff
path: root/llvm/tools/llvm-objcopy/ELF/Object.cpp
diff options
context:
space:
mode:
authorAlexey Lapshin <a.v.lapshin@mail.ru>2020-10-24 17:35:55 +0300
committerAlexey Lapshin <a.v.lapshin@mail.ru>2021-03-10 23:50:04 +0300
commit4f16e177e104eb80589311dc3cc1b5355a7e41bb (patch)
tree06e72462e979bc7c50f01b60401bfe81db406d74 /llvm/tools/llvm-objcopy/ELF/Object.cpp
parent619c1505f9445501551ffedd85cf361a4c5917f0 (diff)
downloadllvm-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.cpp95
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();
}