aboutsummaryrefslogtreecommitdiff
path: root/tools/llvm-objcopy/ELF/Object.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tools/llvm-objcopy/ELF/Object.cpp')
-rw-r--r--tools/llvm-objcopy/ELF/Object.cpp252
1 files changed, 132 insertions, 120 deletions
diff --git a/tools/llvm-objcopy/ELF/Object.cpp b/tools/llvm-objcopy/ELF/Object.cpp
index fa696380e17c..74145dad6e6b 100644
--- a/tools/llvm-objcopy/ELF/Object.cpp
+++ b/tools/llvm-objcopy/ELF/Object.cpp
@@ -397,7 +397,7 @@ void SectionWriter::visit(const OwnedDataSection &Sec) {
llvm::copy(Sec.Data, Out.getBufferStart() + Sec.Offset);
}
-static const std::vector<uint8_t> ZlibGnuMagic = {'Z', 'L', 'I', 'B'};
+static constexpr std::array<uint8_t, 4> ZlibGnuMagic = {{'Z', 'L', 'I', 'B'}};
static bool isDataGnuCompressed(ArrayRef<uint8_t> Data) {
return Data.size() > ZlibGnuMagic.size() &&
@@ -665,7 +665,7 @@ void SymbolTableSection::addSymbol(Twine Name, uint8_t Bind, uint8_t Type,
Sym.Visibility = Visibility;
Sym.Size = SymbolSize;
Sym.Index = Symbols.size();
- Symbols.emplace_back(llvm::make_unique<Symbol>(Sym));
+ Symbols.emplace_back(std::make_unique<Symbol>(Sym));
Size += this->EntrySize;
}
@@ -1055,29 +1055,28 @@ void GroupSection::accept(MutableSectionVisitor &Visitor) {
}
// Returns true IFF a section is wholly inside the range of a segment
-static bool sectionWithinSegment(const SectionBase &Section,
- const Segment &Segment) {
+static bool sectionWithinSegment(const SectionBase &Sec, const Segment &Seg) {
// If a section is empty it should be treated like it has a size of 1. This is
// to clarify the case when an empty section lies on a boundary between two
// segments and ensures that the section "belongs" to the second segment and
// not the first.
- uint64_t SecSize = Section.Size ? Section.Size : 1;
+ uint64_t SecSize = Sec.Size ? Sec.Size : 1;
- if (Section.Type == SHT_NOBITS) {
- if (!(Section.Flags & SHF_ALLOC))
+ if (Sec.Type == SHT_NOBITS) {
+ if (!(Sec.Flags & SHF_ALLOC))
return false;
- bool SectionIsTLS = Section.Flags & SHF_TLS;
- bool SegmentIsTLS = Segment.Type == PT_TLS;
+ bool SectionIsTLS = Sec.Flags & SHF_TLS;
+ bool SegmentIsTLS = Seg.Type == PT_TLS;
if (SectionIsTLS != SegmentIsTLS)
return false;
- return Segment.VAddr <= Section.Addr &&
- Segment.VAddr + Segment.MemSize >= Section.Addr + SecSize;
+ return Seg.VAddr <= Sec.Addr &&
+ Seg.VAddr + Seg.MemSize >= Sec.Addr + SecSize;
}
- return Segment.Offset <= Section.OriginalOffset &&
- Segment.Offset + Segment.FileSize >= Section.OriginalOffset + SecSize;
+ return Seg.Offset <= Sec.OriginalOffset &&
+ Seg.Offset + Seg.FileSize >= Sec.OriginalOffset + SecSize;
}
// Returns true IFF a segment's original offset is inside of another segment's
@@ -1113,7 +1112,7 @@ void BasicELFBuilder::initFileHeader() {
Obj->OSABI = ELFOSABI_NONE;
Obj->ABIVersion = 0;
Obj->Entry = 0x0;
- Obj->Machine = EMachine;
+ Obj->Machine = EM_NONE;
Obj->Version = 1;
}
@@ -1141,8 +1140,8 @@ SymbolTableSection *BasicELFBuilder::addSymTab(StringTableSection *StrTab) {
}
void BasicELFBuilder::initSections() {
- for (auto &Section : Obj->sections())
- Section.initialize(Obj->sections());
+ for (SectionBase &Sec : Obj->sections())
+ Sec.initialize(Obj->sections());
}
void BinaryELFBuilder::addData(SymbolTableSection *SymTab) {
@@ -1161,11 +1160,12 @@ void BinaryELFBuilder::addData(SymbolTableSection *SymTab) {
Twine Prefix = Twine("_binary_") + SanitizedFilename;
SymTab->addSymbol(Prefix + "_start", STB_GLOBAL, STT_NOTYPE, &DataSection,
- /*Value=*/0, STV_DEFAULT, 0, 0);
+ /*Value=*/0, NewSymbolVisibility, 0, 0);
SymTab->addSymbol(Prefix + "_end", STB_GLOBAL, STT_NOTYPE, &DataSection,
- /*Value=*/DataSection.Size, STV_DEFAULT, 0, 0);
+ /*Value=*/DataSection.Size, NewSymbolVisibility, 0, 0);
SymTab->addSymbol(Prefix + "_size", STB_GLOBAL, STT_NOTYPE, nullptr,
- /*Value=*/DataSection.Size, STV_DEFAULT, SHN_ABS, 0);
+ /*Value=*/DataSection.Size, NewSymbolVisibility, SHN_ABS,
+ 0);
}
std::unique_ptr<Object> BinaryELFBuilder::build() {
@@ -1255,10 +1255,9 @@ template <class ELFT> void ELFBuilder<ELFT>::findEhdrOffset() {
if (!ExtractPartition)
return;
- for (const SectionBase &Section : Obj.sections()) {
- if (Section.Type == SHT_LLVM_PART_EHDR &&
- Section.Name == *ExtractPartition) {
- EhdrOffset = Section.Offset;
+ for (const SectionBase &Sec : Obj.sections()) {
+ if (Sec.Type == SHT_LLVM_PART_EHDR && Sec.Name == *ExtractPartition) {
+ EhdrOffset = Sec.Offset;
return;
}
}
@@ -1287,15 +1286,12 @@ void ELFBuilder<ELFT>::readProgramHeaders(const ELFFile<ELFT> &HeadersFile) {
Seg.MemSize = Phdr.p_memsz;
Seg.Align = Phdr.p_align;
Seg.Index = Index++;
- for (SectionBase &Section : Obj.sections()) {
- if (sectionWithinSegment(Section, Seg)) {
- Seg.addSection(&Section);
- if (!Section.ParentSegment ||
- Section.ParentSegment->Offset > Seg.Offset) {
- Section.ParentSegment = &Seg;
- }
+ for (SectionBase &Sec : Obj.sections())
+ if (sectionWithinSegment(Sec, Seg)) {
+ Seg.addSection(&Sec);
+ if (!Sec.ParentSegment || Sec.ParentSegment->Offset > Seg.Offset)
+ Sec.ParentSegment = &Seg;
}
- }
}
auto &ElfHdr = Obj.ElfHdrSegment;
@@ -1531,7 +1527,7 @@ template <class ELFT> void ELFBuilder<ELFT>::readSectionHeaders() {
}
}
-template <class ELFT> void ELFBuilder<ELFT>::readSections() {
+template <class ELFT> void ELFBuilder<ELFT>::readSections(bool EnsureSymtab) {
// If a section index table exists we'll need to initialize it before we
// initialize the symbol table because the symbol table might need to
// reference it.
@@ -1544,16 +1540,37 @@ template <class ELFT> void ELFBuilder<ELFT>::readSections() {
if (Obj.SymbolTable) {
Obj.SymbolTable->initialize(Obj.sections());
initSymbolTable(Obj.SymbolTable);
+ } else if (EnsureSymtab) {
+ // Reuse the existing SHT_STRTAB section if exists.
+ StringTableSection *StrTab = nullptr;
+ for (auto &Sec : Obj.sections()) {
+ if (Sec.Type == ELF::SHT_STRTAB && !(Sec.Flags & SHF_ALLOC)) {
+ StrTab = static_cast<StringTableSection *>(&Sec);
+
+ // Prefer .strtab to .shstrtab.
+ if (Obj.SectionNames != &Sec)
+ break;
+ }
+ }
+ if (!StrTab)
+ StrTab = &Obj.addSection<StringTableSection>();
+
+ SymbolTableSection &SymTab = Obj.addSection<SymbolTableSection>();
+ SymTab.Name = ".symtab";
+ SymTab.Link = StrTab->Index;
+ SymTab.initialize(Obj.sections());
+ SymTab.addSymbol("", 0, 0, nullptr, 0, 0, 0, 0);
+ Obj.SymbolTable = &SymTab;
}
// Now that all sections and symbols have been added we can add
// relocations that reference symbols and set the link and info fields for
// relocation sections.
- for (auto &Section : Obj.sections()) {
- if (&Section == Obj.SymbolTable)
+ for (auto &Sec : Obj.sections()) {
+ if (&Sec == Obj.SymbolTable)
continue;
- Section.initialize(Obj.sections());
- if (auto RelSec = dyn_cast<RelocationSection>(&Section)) {
+ Sec.initialize(Obj.sections());
+ if (auto RelSec = dyn_cast<RelocationSection>(&Sec)) {
auto Shdr = unwrapOrError(ElfFile.sections()).begin() + RelSec->Index;
if (RelSec->Type == SHT_REL)
initRelocations(RelSec, Obj.SymbolTable,
@@ -1561,7 +1578,7 @@ template <class ELFT> void ELFBuilder<ELFT>::readSections() {
else
initRelocations(RelSec, Obj.SymbolTable,
unwrapOrError(ElfFile.relas(Shdr)));
- } else if (auto GroupSec = dyn_cast<GroupSection>(&Section)) {
+ } else if (auto GroupSec = dyn_cast<GroupSection>(&Sec)) {
initGroupSection(GroupSec);
}
}
@@ -1582,7 +1599,7 @@ template <class ELFT> void ELFBuilder<ELFT>::readSections() {
" is not a string table");
}
-template <class ELFT> void ELFBuilder<ELFT>::build() {
+template <class ELFT> void ELFBuilder<ELFT>::build(bool EnsureSymtab) {
readSectionHeaders();
findEhdrOffset();
@@ -1601,7 +1618,7 @@ template <class ELFT> void ELFBuilder<ELFT>::build() {
Obj.Entry = Ehdr.e_entry;
Obj.Flags = Ehdr.e_flags;
- readSections();
+ readSections(EnsureSymtab);
readProgramHeaders(HeadersFile);
}
@@ -1609,8 +1626,8 @@ Writer::~Writer() {}
Reader::~Reader() {}
-std::unique_ptr<Object> BinaryReader::create() const {
- return BinaryELFBuilder(MInfo.EMachine, MemBuf).build();
+std::unique_ptr<Object> BinaryReader::create(bool /*EnsureSymtab*/) const {
+ return BinaryELFBuilder(MemBuf, NewSymbolVisibility).build();
}
Expected<std::vector<IHexRecord>> IHexReader::parse() const {
@@ -1639,28 +1656,28 @@ Expected<std::vector<IHexRecord>> IHexReader::parse() const {
return std::move(Records);
}
-std::unique_ptr<Object> IHexReader::create() const {
+std::unique_ptr<Object> IHexReader::create(bool /*EnsureSymtab*/) const {
std::vector<IHexRecord> Records = unwrapOrError(parse());
return IHexELFBuilder(Records).build();
}
-std::unique_ptr<Object> ELFReader::create() const {
- auto Obj = llvm::make_unique<Object>();
+std::unique_ptr<Object> ELFReader::create(bool EnsureSymtab) const {
+ auto Obj = std::make_unique<Object>();
if (auto *O = dyn_cast<ELFObjectFile<ELF32LE>>(Bin)) {
ELFBuilder<ELF32LE> Builder(*O, *Obj, ExtractPartition);
- Builder.build();
+ Builder.build(EnsureSymtab);
return Obj;
} else if (auto *O = dyn_cast<ELFObjectFile<ELF64LE>>(Bin)) {
ELFBuilder<ELF64LE> Builder(*O, *Obj, ExtractPartition);
- Builder.build();
+ Builder.build(EnsureSymtab);
return Obj;
} else if (auto *O = dyn_cast<ELFObjectFile<ELF32BE>>(Bin)) {
ELFBuilder<ELF32BE> Builder(*O, *Obj, ExtractPartition);
- Builder.build();
+ Builder.build(EnsureSymtab);
return Obj;
} else if (auto *O = dyn_cast<ELFObjectFile<ELF64BE>>(Bin)) {
ELFBuilder<ELF64BE> Builder(*O, *Obj, ExtractPartition);
- Builder.build();
+ Builder.build(EnsureSymtab);
return Obj;
}
error("invalid file type");
@@ -1693,7 +1710,7 @@ template <class ELFT> void ELFWriter<ELFT>::writeEhdr() {
Ehdr.e_ehsize = sizeof(Elf_Ehdr);
if (WriteSectionHeaders && Obj.sections().size() != 0) {
Ehdr.e_shentsize = sizeof(Elf_Shdr);
- Ehdr.e_shoff = Obj.SHOffset;
+ Ehdr.e_shoff = Obj.SHOff;
// """
// If the number of sections is greater than or equal to
// SHN_LORESERVE (0xff00), this member has the value zero and the actual
@@ -1732,7 +1749,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.SHOffset);
+ *reinterpret_cast<Elf_Shdr *>(Buf.getBufferStart() + Obj.SHOff);
Shdr.sh_name = 0;
Shdr.sh_type = SHT_NULL;
Shdr.sh_flags = 0;
@@ -1862,26 +1879,13 @@ void Object::sortSections() {
});
}
-static uint64_t alignToAddr(uint64_t Offset, uint64_t Addr, uint64_t Align) {
- // Calculate Diff such that (Offset + Diff) & -Align == Addr & -Align.
- if (Align == 0)
- Align = 1;
- auto Diff =
- static_cast<int64_t>(Addr % Align) - static_cast<int64_t>(Offset % Align);
- // We only want to add to Offset, however, so if Diff < 0 we can add Align and
- // (Offset + Diff) & -Align == Addr & -Align will still hold.
- if (Diff < 0)
- Diff += Align;
- return Offset + Diff;
-}
-
// Orders segments such that if x = y->ParentSegment then y comes before x.
static void orderSegments(std::vector<Segment *> &Segments) {
llvm::stable_sort(Segments, compareSegmentsByOffset);
}
// This function finds a consistent layout for a list of segments starting from
-// an Offset. It assumes that Segments have been sorted by OrderSegments and
+// an Offset. It assumes that Segments have been sorted by orderSegments and
// returns an Offset one past the end of the last segment.
static uint64_t layoutSegments(std::vector<Segment *> &Segments,
uint64_t Offset) {
@@ -1902,8 +1906,8 @@ static uint64_t layoutSegments(std::vector<Segment *> &Segments,
Seg->Offset =
Parent->Offset + Seg->OriginalOffset - Parent->OriginalOffset;
} else {
- Offset = alignToAddr(Offset, Seg->VAddr, Seg->Align);
- Seg->Offset = Offset;
+ Seg->Offset =
+ alignTo(Offset, std::max<uint64_t>(Seg->Align, 1), Seg->VAddr);
}
Offset = std::max(Offset, Seg->Offset + Seg->FileSize);
}
@@ -1925,17 +1929,17 @@ static uint64_t layoutSections(Range Sections, uint64_t Offset) {
// of the segment we can assign a new offset to the section. For sections not
// covered by segments we can just bump Offset to the next valid location.
uint32_t Index = 1;
- for (auto &Section : Sections) {
- Section.Index = Index++;
- if (Section.ParentSegment != nullptr) {
- auto Segment = *Section.ParentSegment;
- Section.Offset =
- Segment.Offset + (Section.OriginalOffset - Segment.OriginalOffset);
+ for (auto &Sec : Sections) {
+ Sec.Index = Index++;
+ if (Sec.ParentSegment != nullptr) {
+ auto Segment = *Sec.ParentSegment;
+ Sec.Offset =
+ Segment.Offset + (Sec.OriginalOffset - Segment.OriginalOffset);
} else {
- Offset = alignTo(Offset, Section.Align == 0 ? 1 : Section.Align);
- Section.Offset = Offset;
- if (Section.Type != SHT_NOBITS)
- Offset += Section.Size;
+ Offset = alignTo(Offset, Sec.Align == 0 ? 1 : Sec.Align);
+ Sec.Offset = Offset;
+ if (Sec.Type != SHT_NOBITS)
+ Offset += Sec.Size;
}
}
return Offset;
@@ -1971,16 +1975,16 @@ template <class ELFT> void ELFWriter<ELFT>::assignOffsets() {
// Offset so that SHOffset is valid.
if (WriteSectionHeaders)
Offset = alignTo(Offset, sizeof(Elf_Addr));
- Obj.SHOffset = Offset;
+ Obj.SHOff = Offset;
}
template <class ELFT> size_t ELFWriter<ELFT>::totalSize() const {
// We already have the section header offset so we can calculate the total
// size by just adding up the size of each section header.
if (!WriteSectionHeaders)
- return Obj.SHOffset;
+ return Obj.SHOff;
size_t ShdrCount = Obj.sections().size() + 1; // Includes null shdr.
- return Obj.SHOffset + ShdrCount * sizeof(Elf_Shdr);
+ return Obj.SHOff + ShdrCount * sizeof(Elf_Shdr);
}
template <class ELFT> Error ELFWriter<ELFT>::write() {
@@ -1995,6 +1999,25 @@ template <class ELFT> Error ELFWriter<ELFT>::write() {
return Buf.commit();
}
+static Error removeUnneededSections(Object &Obj) {
+ // We can remove an empty symbol table from non-relocatable objects.
+ // Relocatable objects typically have relocation sections whose
+ // sh_link field points to .symtab, so we can't remove .symtab
+ // even if it is empty.
+ if (Obj.isRelocatable() || Obj.SymbolTable == nullptr ||
+ !Obj.SymbolTable->empty())
+ return Error::success();
+
+ // .strtab can be used for section names. In such a case we shouldn't
+ // remove it.
+ auto *StrTab = Obj.SymbolTable->getStrTab() == Obj.SectionNames
+ ? nullptr
+ : Obj.SymbolTable->getStrTab();
+ return Obj.removeSections(false, [&](const SectionBase &Sec) {
+ return &Sec == Obj.SymbolTable || &Sec == StrTab;
+ });
+}
+
template <class ELFT> Error ELFWriter<ELFT>::finalize() {
// It could happen that SectionNames has been removed and yet the user wants
// a section header table output. We need to throw an error if a user tries
@@ -2004,6 +2027,8 @@ template <class ELFT> Error ELFWriter<ELFT>::finalize() {
"cannot write section header table because "
"section header string table was removed");
+ if (Error E = removeUnneededSections(Obj))
+ return E;
Obj.sortSections();
// We need to assign indexes before we perform layout because we need to know
@@ -2045,9 +2070,8 @@ template <class ELFT> Error ELFWriter<ELFT>::finalize() {
// Make sure we add the names of all the sections. Importantly this must be
// done after we decide to add or remove SectionIndexes.
if (Obj.SectionNames != nullptr)
- for (const auto &Section : Obj.sections()) {
- Obj.SectionNames->addString(Section.Name);
- }
+ for (const SectionBase &Sec : Obj.sections())
+ Obj.SectionNames->addString(Sec.Name);
initEhdrSegment();
@@ -2055,8 +2079,8 @@ template <class ELFT> Error ELFWriter<ELFT>::finalize() {
// Also, the output arch may not be the same as the input arch, so fix up
// size-related fields before doing layout calculations.
uint64_t Index = 0;
- auto SecSizer = llvm::make_unique<ELFSectionSizer<ELFT>>();
- for (auto &Sec : Obj.sections()) {
+ auto SecSizer = std::make_unique<ELFSectionSizer<ELFT>>();
+ for (SectionBase &Sec : Obj.sections()) {
Sec.Index = Index++;
Sec.accept(*SecSizer);
}
@@ -2082,40 +2106,36 @@ template <class ELFT> Error ELFWriter<ELFT>::finalize() {
// Finally now that all offsets and indexes have been set we can finalize any
// remaining issues.
- uint64_t Offset = Obj.SHOffset + sizeof(Elf_Shdr);
- for (SectionBase &Section : Obj.sections()) {
- Section.HeaderOffset = Offset;
+ uint64_t Offset = Obj.SHOff + sizeof(Elf_Shdr);
+ for (SectionBase &Sec : Obj.sections()) {
+ Sec.HeaderOffset = Offset;
Offset += sizeof(Elf_Shdr);
if (WriteSectionHeaders)
- Section.NameIndex = Obj.SectionNames->findIndex(Section.Name);
- Section.finalize();
+ Sec.NameIndex = Obj.SectionNames->findIndex(Sec.Name);
+ Sec.finalize();
}
if (Error E = Buf.allocate(totalSize()))
return E;
- SecWriter = llvm::make_unique<ELFSectionWriter<ELFT>>(Buf);
+ SecWriter = std::make_unique<ELFSectionWriter<ELFT>>(Buf);
return Error::success();
}
Error BinaryWriter::write() {
- for (auto &Section : Obj.sections())
- if (Section.Flags & SHF_ALLOC)
- Section.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<Segment *> OrderedSegments;
- for (SectionBase &Section : Obj.sections())
- if ((Section.Flags & SHF_ALLOC) != 0 && Section.ParentSegment != nullptr)
- OrderedSegments.push_back(Section.ParentSegment);
+ 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
// virtual addresses, since a binary output is used for cases like ROM
@@ -2130,7 +2150,7 @@ Error BinaryWriter::finalize() {
llvm::stable_sort(OrderedSegments, compareSegmentsByPAddr);
// Because we add a ParentSegment for each section we might have duplicate
- // segments in OrderedSegments. If there were duplicates then LayoutSegments
+ // segments in OrderedSegments. If there were duplicates then layoutSegments
// would do very strange things.
auto End =
std::unique(std::begin(OrderedSegments), std::end(OrderedSegments));
@@ -2158,28 +2178,20 @@ 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<SectionBase *> AllocatedSections;
- for (SectionBase &Section : Obj.sections())
- if (Section.Flags & SHF_ALLOC)
- AllocatedSections.push_back(&Section);
- 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
+ // 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 *Section : AllocatedSections)
- if (Section->Type != SHT_NOBITS)
- TotalSize = std::max(TotalSize, Section->Offset + Section->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;
- SecWriter = llvm::make_unique<BinarySectionWriter>(Buf);
+ SecWriter = std::make_unique<BinarySectionWriter>(Buf);
return Error::success();
}
@@ -2259,17 +2271,17 @@ Error IHexWriter::finalize() {
// If any section we're to write has segment then we
// switch to using physical addresses. Otherwise we
// use section virtual address.
- for (auto &Section : Obj.sections())
- if (ShouldWrite(Section) && IsInPtLoad(Section)) {
+ for (const SectionBase &Sec : Obj.sections())
+ if (ShouldWrite(Sec) && IsInPtLoad(Sec)) {
UseSegments = true;
break;
}
- for (auto &Section : Obj.sections())
- if (ShouldWrite(Section) && (!UseSegments || IsInPtLoad(Section))) {
- if (Error E = checkSection(Section))
+ for (const SectionBase &Sec : Obj.sections())
+ if (ShouldWrite(Sec) && (!UseSegments || IsInPtLoad(Sec))) {
+ if (Error E = checkSection(Sec))
return E;
- Sections.insert(&Section);
+ Sections.insert(&Sec);
}
IHexSectionWriterBase LengthCalc(Buf);