From 43519798b48a7c83c2aa78d714e9c40af15b0b85 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Wed, 4 Sep 2019 09:35:32 +0000 Subject: [PATCH] [llvm-objcopy] Add objcopy::elf::Object::allocSections to simplify loops on SHF_ALLOC sections Reviewed By: jhenderson Differential Revision: https://reviews.llvm.org/D67142 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@370860 91177308-0d34-0410-b5e6-96231b3b80d8 --- tools/llvm-objcopy/ELF/Object.cpp | 28 ++++++++-------------------- tools/llvm-objcopy/ELF/Object.h | 15 +++++++++++++-- 2 files changed, 21 insertions(+), 22 deletions(-) diff --git a/tools/llvm-objcopy/ELF/Object.cpp b/tools/llvm-objcopy/ELF/Object.cpp index f2b606d28d6..44e6bf54b28 100644 --- a/tools/llvm-objcopy/ELF/Object.cpp +++ b/tools/llvm-objcopy/ELF/Object.cpp @@ -2101,23 +2101,19 @@ template Error ELFWriter::finalize() { } Error BinaryWriter::write() { - for (const SectionBase &Sec : Obj.sections()) - if (Sec.Flags & SHF_ALLOC) - Sec.accept(*SecWriter); + for (const SectionBase &Sec : Obj.allocSections()) + Sec.accept(*SecWriter); return Buf.commit(); } Error BinaryWriter::finalize() { - // TODO: Create a filter range to construct OrderedSegments from so that this - // code can be deduped with assignOffsets above. This should also solve the - // todo below for LayoutSections. // We need a temporary list of segments that has a special order to it // so that we know that anytime ->ParentSegment is set that segment has // already had it's offset properly set. We only want to consider the segments // that will affect layout of allocated sections so we only add those. std::vector OrderedSegments; - for (const SectionBase &Sec : Obj.sections()) - if ((Sec.Flags & SHF_ALLOC) != 0 && Sec.ParentSegment != nullptr) + for (const SectionBase &Sec : Obj.allocSections()) + if (Sec.ParentSegment != nullptr) OrderedSegments.push_back(Sec.ParentSegment); // For binary output, we're going to use physical addresses instead of @@ -2161,24 +2157,16 @@ Error BinaryWriter::finalize() { } } - // TODO: generalize layoutSections to take a range. Pass a special range - // constructed from an iterator that skips values for which a predicate does - // not hold. Then pass such a range to layoutSections instead of constructing - // AllocatedSections here. - std::vector AllocatedSections; - for (SectionBase &Sec : Obj.sections()) - if (Sec.Flags & SHF_ALLOC) - AllocatedSections.push_back(&Sec); - layoutSections(make_pointee_range(AllocatedSections), Offset); + layoutSections(Obj.allocSections(), Offset); // Now that every section has been laid out we just need to compute the total // file size. This might not be the same as the offset returned by // layoutSections, because we want to truncate the last segment to the end of // its last section, to match GNU objcopy's behaviour. TotalSize = 0; - for (SectionBase *Sec : AllocatedSections) - if (Sec->Type != SHT_NOBITS) - TotalSize = std::max(TotalSize, Sec->Offset + Sec->Size); + for (const SectionBase &Sec : Obj.allocSections()) + if (Sec.Type != SHT_NOBITS) + TotalSize = std::max(TotalSize, Sec.Offset + Sec.Size); if (Error E = Buf.allocate(TotalSize)) return E; diff --git a/tools/llvm-objcopy/ELF/Object.h b/tools/llvm-objcopy/ELF/Object.h index 42844dae3b4..70be6bed422 100644 --- a/tools/llvm-objcopy/ELF/Object.h +++ b/tools/llvm-objcopy/ELF/Object.h @@ -57,8 +57,8 @@ class SectionTableRef { : Sections(Secs) {} SectionTableRef(const SectionTableRef &) = default; - iterator begin() { return iterator(Sections.data()); } - iterator end() { return iterator(Sections.data() + Sections.size()); } + iterator begin() const { return iterator(Sections.data()); } + iterator end() const { return iterator(Sections.data() + Sections.size()); } size_t size() const { return Sections.size(); } SectionBase *getSection(uint32_t Index, Twine ErrMsg); @@ -994,6 +994,10 @@ class Object { std::vector Segments; std::vector RemovedSections; + static bool sectionIsAlloc(const SectionBase &Sec) { + return Sec.Flags & ELF::SHF_ALLOC; + }; + public: template using Range = iterator_range< @@ -1032,6 +1036,13 @@ class Object { ConstRange sections() const { return make_pointee_range(Sections); } + iterator_range< + filter_iterator::const_iterator>, + decltype(§ionIsAlloc)>> + allocSections() const { + return make_filter_range(make_pointee_range(Sections), sectionIsAlloc); + } + SectionBase *findSection(StringRef Name) { auto SecIt = find_if(Sections, [&](const SecPtr &Sec) { return Sec->Name == Name; });