xref: /llvm-project/llvm/lib/ObjCopy/ELF/ELFObject.cpp (revision 10772807ab72ce2b68d76816f8753219b2acbac3)
125d7b4fbSAlexey Lapshin //===- ELFObject.cpp ------------------------------------------------------===//
225d7b4fbSAlexey Lapshin //
325d7b4fbSAlexey Lapshin // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
425d7b4fbSAlexey Lapshin // See https://llvm.org/LICENSE.txt for license information.
525d7b4fbSAlexey Lapshin // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
625d7b4fbSAlexey Lapshin //
725d7b4fbSAlexey Lapshin //===----------------------------------------------------------------------===//
825d7b4fbSAlexey Lapshin 
925d7b4fbSAlexey Lapshin #include "ELFObject.h"
1025d7b4fbSAlexey Lapshin #include "llvm/ADT/ArrayRef.h"
1125d7b4fbSAlexey Lapshin #include "llvm/ADT/STLExtras.h"
1225d7b4fbSAlexey Lapshin #include "llvm/ADT/StringRef.h"
1325d7b4fbSAlexey Lapshin #include "llvm/ADT/Twine.h"
1425d7b4fbSAlexey Lapshin #include "llvm/ADT/iterator_range.h"
1525d7b4fbSAlexey Lapshin #include "llvm/BinaryFormat/ELF.h"
169bb4cd59SFangrui Song #include "llvm/MC/MCELFExtras.h"
1725d7b4fbSAlexey Lapshin #include "llvm/MC/MCTargetOptions.h"
1825d7b4fbSAlexey Lapshin #include "llvm/Support/Compression.h"
1925d7b4fbSAlexey Lapshin #include "llvm/Support/Endian.h"
2025d7b4fbSAlexey Lapshin #include "llvm/Support/ErrorHandling.h"
2125d7b4fbSAlexey Lapshin #include "llvm/Support/Path.h"
2225d7b4fbSAlexey Lapshin #include <algorithm>
2325d7b4fbSAlexey Lapshin #include <cstddef>
2425d7b4fbSAlexey Lapshin #include <cstdint>
2525d7b4fbSAlexey Lapshin #include <iterator>
2625d7b4fbSAlexey Lapshin #include <unordered_set>
2725d7b4fbSAlexey Lapshin #include <utility>
2825d7b4fbSAlexey Lapshin #include <vector>
2925d7b4fbSAlexey Lapshin 
3025d7b4fbSAlexey Lapshin using namespace llvm;
3125d7b4fbSAlexey Lapshin using namespace llvm::ELF;
3225d7b4fbSAlexey Lapshin using namespace llvm::objcopy::elf;
3325d7b4fbSAlexey Lapshin using namespace llvm::object;
3427633538SFangrui Song using namespace llvm::support;
3525d7b4fbSAlexey Lapshin 
3625d7b4fbSAlexey Lapshin template <class ELFT> void ELFWriter<ELFT>::writePhdr(const Segment &Seg) {
3725d7b4fbSAlexey Lapshin   uint8_t *B = reinterpret_cast<uint8_t *>(Buf->getBufferStart()) +
3825d7b4fbSAlexey Lapshin                Obj.ProgramHdrSegment.Offset + Seg.Index * sizeof(Elf_Phdr);
3925d7b4fbSAlexey Lapshin   Elf_Phdr &Phdr = *reinterpret_cast<Elf_Phdr *>(B);
4025d7b4fbSAlexey Lapshin   Phdr.p_type = Seg.Type;
4125d7b4fbSAlexey Lapshin   Phdr.p_flags = Seg.Flags;
4225d7b4fbSAlexey Lapshin   Phdr.p_offset = Seg.Offset;
4325d7b4fbSAlexey Lapshin   Phdr.p_vaddr = Seg.VAddr;
4425d7b4fbSAlexey Lapshin   Phdr.p_paddr = Seg.PAddr;
4525d7b4fbSAlexey Lapshin   Phdr.p_filesz = Seg.FileSize;
4625d7b4fbSAlexey Lapshin   Phdr.p_memsz = Seg.MemSize;
4725d7b4fbSAlexey Lapshin   Phdr.p_align = Seg.Align;
4825d7b4fbSAlexey Lapshin }
4925d7b4fbSAlexey Lapshin 
5025d7b4fbSAlexey Lapshin Error SectionBase::removeSectionReferences(
5125d7b4fbSAlexey Lapshin     bool, function_ref<bool(const SectionBase *)>) {
5225d7b4fbSAlexey Lapshin   return Error::success();
5325d7b4fbSAlexey Lapshin }
5425d7b4fbSAlexey Lapshin 
5525d7b4fbSAlexey Lapshin Error SectionBase::removeSymbols(function_ref<bool(const Symbol &)>) {
5625d7b4fbSAlexey Lapshin   return Error::success();
5725d7b4fbSAlexey Lapshin }
5825d7b4fbSAlexey Lapshin 
5925d7b4fbSAlexey Lapshin Error SectionBase::initialize(SectionTableRef) { return Error::success(); }
6025d7b4fbSAlexey Lapshin void SectionBase::finalize() {}
6125d7b4fbSAlexey Lapshin void SectionBase::markSymbols() {}
6225d7b4fbSAlexey Lapshin void SectionBase::replaceSectionReferences(
6325d7b4fbSAlexey Lapshin     const DenseMap<SectionBase *, SectionBase *> &) {}
6425d7b4fbSAlexey Lapshin void SectionBase::onRemove() {}
6525d7b4fbSAlexey Lapshin 
6625d7b4fbSAlexey Lapshin template <class ELFT> void ELFWriter<ELFT>::writeShdr(const SectionBase &Sec) {
6725d7b4fbSAlexey Lapshin   uint8_t *B =
6825d7b4fbSAlexey Lapshin       reinterpret_cast<uint8_t *>(Buf->getBufferStart()) + Sec.HeaderOffset;
6925d7b4fbSAlexey Lapshin   Elf_Shdr &Shdr = *reinterpret_cast<Elf_Shdr *>(B);
7025d7b4fbSAlexey Lapshin   Shdr.sh_name = Sec.NameIndex;
7125d7b4fbSAlexey Lapshin   Shdr.sh_type = Sec.Type;
7225d7b4fbSAlexey Lapshin   Shdr.sh_flags = Sec.Flags;
7325d7b4fbSAlexey Lapshin   Shdr.sh_addr = Sec.Addr;
7425d7b4fbSAlexey Lapshin   Shdr.sh_offset = Sec.Offset;
7525d7b4fbSAlexey Lapshin   Shdr.sh_size = Sec.Size;
7625d7b4fbSAlexey Lapshin   Shdr.sh_link = Sec.Link;
7725d7b4fbSAlexey Lapshin   Shdr.sh_info = Sec.Info;
7825d7b4fbSAlexey Lapshin   Shdr.sh_addralign = Sec.Align;
7925d7b4fbSAlexey Lapshin   Shdr.sh_entsize = Sec.EntrySize;
8025d7b4fbSAlexey Lapshin }
8125d7b4fbSAlexey Lapshin 
8225d7b4fbSAlexey Lapshin template <class ELFT> Error ELFSectionSizer<ELFT>::visit(Section &) {
8325d7b4fbSAlexey Lapshin   return Error::success();
8425d7b4fbSAlexey Lapshin }
8525d7b4fbSAlexey Lapshin 
8625d7b4fbSAlexey Lapshin template <class ELFT> Error ELFSectionSizer<ELFT>::visit(OwnedDataSection &) {
8725d7b4fbSAlexey Lapshin   return Error::success();
8825d7b4fbSAlexey Lapshin }
8925d7b4fbSAlexey Lapshin 
9025d7b4fbSAlexey Lapshin template <class ELFT> Error ELFSectionSizer<ELFT>::visit(StringTableSection &) {
9125d7b4fbSAlexey Lapshin   return Error::success();
9225d7b4fbSAlexey Lapshin }
9325d7b4fbSAlexey Lapshin 
9425d7b4fbSAlexey Lapshin template <class ELFT>
9525d7b4fbSAlexey Lapshin Error ELFSectionSizer<ELFT>::visit(DynamicRelocationSection &) {
9625d7b4fbSAlexey Lapshin   return Error::success();
9725d7b4fbSAlexey Lapshin }
9825d7b4fbSAlexey Lapshin 
9925d7b4fbSAlexey Lapshin template <class ELFT>
10025d7b4fbSAlexey Lapshin Error ELFSectionSizer<ELFT>::visit(SymbolTableSection &Sec) {
10125d7b4fbSAlexey Lapshin   Sec.EntrySize = sizeof(Elf_Sym);
10225d7b4fbSAlexey Lapshin   Sec.Size = Sec.Symbols.size() * Sec.EntrySize;
10325d7b4fbSAlexey Lapshin   // Align to the largest field in Elf_Sym.
10425d7b4fbSAlexey Lapshin   Sec.Align = ELFT::Is64Bits ? sizeof(Elf_Xword) : sizeof(Elf_Word);
10525d7b4fbSAlexey Lapshin   return Error::success();
10625d7b4fbSAlexey Lapshin }
10725d7b4fbSAlexey Lapshin 
1089bb4cd59SFangrui Song template <bool Is64>
1099bb4cd59SFangrui Song static SmallVector<char, 0> encodeCrel(ArrayRef<Relocation> Relocations) {
1109bb4cd59SFangrui Song   using uint = std::conditional_t<Is64, uint64_t, uint32_t>;
1119bb4cd59SFangrui Song   SmallVector<char, 0> Content;
1129bb4cd59SFangrui Song   raw_svector_ostream OS(Content);
1139bb4cd59SFangrui Song   ELF::encodeCrel<Is64>(OS, Relocations, [&](const Relocation &R) {
1149bb4cd59SFangrui Song     uint32_t CurSymIdx = R.RelocSymbol ? R.RelocSymbol->Index : 0;
1159bb4cd59SFangrui Song     return ELF::Elf_Crel<Is64>{static_cast<uint>(R.Offset), CurSymIdx, R.Type,
1169bb4cd59SFangrui Song                                std::make_signed_t<uint>(R.Addend)};
1179bb4cd59SFangrui Song   });
1189bb4cd59SFangrui Song   return Content;
1199bb4cd59SFangrui Song }
1209bb4cd59SFangrui Song 
12125d7b4fbSAlexey Lapshin template <class ELFT>
12225d7b4fbSAlexey Lapshin Error ELFSectionSizer<ELFT>::visit(RelocationSection &Sec) {
1239bb4cd59SFangrui Song   if (Sec.Type == SHT_CREL) {
1249bb4cd59SFangrui Song     Sec.Size = encodeCrel<ELFT::Is64Bits>(Sec.Relocations).size();
1259bb4cd59SFangrui Song   } else {
12625d7b4fbSAlexey Lapshin     Sec.EntrySize = Sec.Type == SHT_REL ? sizeof(Elf_Rel) : sizeof(Elf_Rela);
12725d7b4fbSAlexey Lapshin     Sec.Size = Sec.Relocations.size() * Sec.EntrySize;
12825d7b4fbSAlexey Lapshin     // Align to the largest field in Elf_Rel(a).
12925d7b4fbSAlexey Lapshin     Sec.Align = ELFT::Is64Bits ? sizeof(Elf_Xword) : sizeof(Elf_Word);
1309bb4cd59SFangrui Song   }
13125d7b4fbSAlexey Lapshin   return Error::success();
13225d7b4fbSAlexey Lapshin }
13325d7b4fbSAlexey Lapshin 
13425d7b4fbSAlexey Lapshin template <class ELFT>
13525d7b4fbSAlexey Lapshin Error ELFSectionSizer<ELFT>::visit(GnuDebugLinkSection &) {
13625d7b4fbSAlexey Lapshin   return Error::success();
13725d7b4fbSAlexey Lapshin }
13825d7b4fbSAlexey Lapshin 
13925d7b4fbSAlexey Lapshin template <class ELFT> Error ELFSectionSizer<ELFT>::visit(GroupSection &Sec) {
14025d7b4fbSAlexey Lapshin   Sec.Size = sizeof(Elf_Word) + Sec.GroupMembers.size() * sizeof(Elf_Word);
14125d7b4fbSAlexey Lapshin   return Error::success();
14225d7b4fbSAlexey Lapshin }
14325d7b4fbSAlexey Lapshin 
14425d7b4fbSAlexey Lapshin template <class ELFT>
14525d7b4fbSAlexey Lapshin Error ELFSectionSizer<ELFT>::visit(SectionIndexSection &) {
14625d7b4fbSAlexey Lapshin   return Error::success();
14725d7b4fbSAlexey Lapshin }
14825d7b4fbSAlexey Lapshin 
14925d7b4fbSAlexey Lapshin template <class ELFT> Error ELFSectionSizer<ELFT>::visit(CompressedSection &) {
15025d7b4fbSAlexey Lapshin   return Error::success();
15125d7b4fbSAlexey Lapshin }
15225d7b4fbSAlexey Lapshin 
15325d7b4fbSAlexey Lapshin template <class ELFT>
15425d7b4fbSAlexey Lapshin Error ELFSectionSizer<ELFT>::visit(DecompressedSection &) {
15525d7b4fbSAlexey Lapshin   return Error::success();
15625d7b4fbSAlexey Lapshin }
15725d7b4fbSAlexey Lapshin 
15825d7b4fbSAlexey Lapshin Error BinarySectionWriter::visit(const SectionIndexSection &Sec) {
15925d7b4fbSAlexey Lapshin   return createStringError(errc::operation_not_permitted,
16025d7b4fbSAlexey Lapshin                            "cannot write symbol section index table '" +
16125d7b4fbSAlexey Lapshin                                Sec.Name + "' ");
16225d7b4fbSAlexey Lapshin }
16325d7b4fbSAlexey Lapshin 
16425d7b4fbSAlexey Lapshin Error BinarySectionWriter::visit(const SymbolTableSection &Sec) {
16525d7b4fbSAlexey Lapshin   return createStringError(errc::operation_not_permitted,
16625d7b4fbSAlexey Lapshin                            "cannot write symbol table '" + Sec.Name +
16725d7b4fbSAlexey Lapshin                                "' out to binary");
16825d7b4fbSAlexey Lapshin }
16925d7b4fbSAlexey Lapshin 
17025d7b4fbSAlexey Lapshin Error BinarySectionWriter::visit(const RelocationSection &Sec) {
17125d7b4fbSAlexey Lapshin   return createStringError(errc::operation_not_permitted,
17225d7b4fbSAlexey Lapshin                            "cannot write relocation section '" + Sec.Name +
17325d7b4fbSAlexey Lapshin                                "' out to binary");
17425d7b4fbSAlexey Lapshin }
17525d7b4fbSAlexey Lapshin 
17625d7b4fbSAlexey Lapshin Error BinarySectionWriter::visit(const GnuDebugLinkSection &Sec) {
17725d7b4fbSAlexey Lapshin   return createStringError(errc::operation_not_permitted,
17825d7b4fbSAlexey Lapshin                            "cannot write '" + Sec.Name + "' out to binary");
17925d7b4fbSAlexey Lapshin }
18025d7b4fbSAlexey Lapshin 
18125d7b4fbSAlexey Lapshin Error BinarySectionWriter::visit(const GroupSection &Sec) {
18225d7b4fbSAlexey Lapshin   return createStringError(errc::operation_not_permitted,
18325d7b4fbSAlexey Lapshin                            "cannot write '" + Sec.Name + "' out to binary");
18425d7b4fbSAlexey Lapshin }
18525d7b4fbSAlexey Lapshin 
18625d7b4fbSAlexey Lapshin Error SectionWriter::visit(const Section &Sec) {
18725d7b4fbSAlexey Lapshin   if (Sec.Type != SHT_NOBITS)
18825d7b4fbSAlexey Lapshin     llvm::copy(Sec.Contents, Out.getBufferStart() + Sec.Offset);
18925d7b4fbSAlexey Lapshin 
19025d7b4fbSAlexey Lapshin   return Error::success();
19125d7b4fbSAlexey Lapshin }
19225d7b4fbSAlexey Lapshin 
19325d7b4fbSAlexey Lapshin static bool addressOverflows32bit(uint64_t Addr) {
19425d7b4fbSAlexey Lapshin   // Sign extended 32 bit addresses (e.g 0xFFFFFFFF80000000) are ok
19525d7b4fbSAlexey Lapshin   return Addr > UINT32_MAX && Addr + 0x80000000 > UINT32_MAX;
19625d7b4fbSAlexey Lapshin }
19725d7b4fbSAlexey Lapshin 
19825d7b4fbSAlexey Lapshin template <class T> static T checkedGetHex(StringRef S) {
19925d7b4fbSAlexey Lapshin   T Value;
20025d7b4fbSAlexey Lapshin   bool Fail = S.getAsInteger(16, Value);
20125d7b4fbSAlexey Lapshin   assert(!Fail);
20225d7b4fbSAlexey Lapshin   (void)Fail;
20325d7b4fbSAlexey Lapshin   return Value;
20425d7b4fbSAlexey Lapshin }
20525d7b4fbSAlexey Lapshin 
20625d7b4fbSAlexey Lapshin // Fills exactly Len bytes of buffer with hexadecimal characters
20725d7b4fbSAlexey Lapshin // representing value 'X'
20825d7b4fbSAlexey Lapshin template <class T, class Iterator>
20925d7b4fbSAlexey Lapshin static Iterator toHexStr(T X, Iterator It, size_t Len) {
21025d7b4fbSAlexey Lapshin   // Fill range with '0'
21125d7b4fbSAlexey Lapshin   std::fill(It, It + Len, '0');
21225d7b4fbSAlexey Lapshin 
21325d7b4fbSAlexey Lapshin   for (long I = Len - 1; I >= 0; --I) {
21425d7b4fbSAlexey Lapshin     unsigned char Mod = static_cast<unsigned char>(X) & 15;
21525d7b4fbSAlexey Lapshin     *(It + I) = hexdigit(Mod, false);
21625d7b4fbSAlexey Lapshin     X >>= 4;
21725d7b4fbSAlexey Lapshin   }
21825d7b4fbSAlexey Lapshin   assert(X == 0);
21925d7b4fbSAlexey Lapshin   return It + Len;
22025d7b4fbSAlexey Lapshin }
22125d7b4fbSAlexey Lapshin 
22225d7b4fbSAlexey Lapshin uint8_t IHexRecord::getChecksum(StringRef S) {
22325d7b4fbSAlexey Lapshin   assert((S.size() & 1) == 0);
22425d7b4fbSAlexey Lapshin   uint8_t Checksum = 0;
22525d7b4fbSAlexey Lapshin   while (!S.empty()) {
22625d7b4fbSAlexey Lapshin     Checksum += checkedGetHex<uint8_t>(S.take_front(2));
22725d7b4fbSAlexey Lapshin     S = S.drop_front(2);
22825d7b4fbSAlexey Lapshin   }
22925d7b4fbSAlexey Lapshin   return -Checksum;
23025d7b4fbSAlexey Lapshin }
23125d7b4fbSAlexey Lapshin 
23225d7b4fbSAlexey Lapshin IHexLineData IHexRecord::getLine(uint8_t Type, uint16_t Addr,
23325d7b4fbSAlexey Lapshin                                  ArrayRef<uint8_t> Data) {
23425d7b4fbSAlexey Lapshin   IHexLineData Line(getLineLength(Data.size()));
23525d7b4fbSAlexey Lapshin   assert(Line.size());
23625d7b4fbSAlexey Lapshin   auto Iter = Line.begin();
23725d7b4fbSAlexey Lapshin   *Iter++ = ':';
23825d7b4fbSAlexey Lapshin   Iter = toHexStr(Data.size(), Iter, 2);
23925d7b4fbSAlexey Lapshin   Iter = toHexStr(Addr, Iter, 4);
24025d7b4fbSAlexey Lapshin   Iter = toHexStr(Type, Iter, 2);
24125d7b4fbSAlexey Lapshin   for (uint8_t X : Data)
24225d7b4fbSAlexey Lapshin     Iter = toHexStr(X, Iter, 2);
24325d7b4fbSAlexey Lapshin   StringRef S(Line.data() + 1, std::distance(Line.begin() + 1, Iter));
24425d7b4fbSAlexey Lapshin   Iter = toHexStr(getChecksum(S), Iter, 2);
24525d7b4fbSAlexey Lapshin   *Iter++ = '\r';
24625d7b4fbSAlexey Lapshin   *Iter++ = '\n';
24725d7b4fbSAlexey Lapshin   assert(Iter == Line.end());
24825d7b4fbSAlexey Lapshin   return Line;
24925d7b4fbSAlexey Lapshin }
25025d7b4fbSAlexey Lapshin 
25125d7b4fbSAlexey Lapshin static Error checkRecord(const IHexRecord &R) {
25225d7b4fbSAlexey Lapshin   switch (R.Type) {
25325d7b4fbSAlexey Lapshin   case IHexRecord::Data:
25425d7b4fbSAlexey Lapshin     if (R.HexData.size() == 0)
25525d7b4fbSAlexey Lapshin       return createStringError(
25625d7b4fbSAlexey Lapshin           errc::invalid_argument,
25725d7b4fbSAlexey Lapshin           "zero data length is not allowed for data records");
25825d7b4fbSAlexey Lapshin     break;
25925d7b4fbSAlexey Lapshin   case IHexRecord::EndOfFile:
26025d7b4fbSAlexey Lapshin     break;
26125d7b4fbSAlexey Lapshin   case IHexRecord::SegmentAddr:
26225d7b4fbSAlexey Lapshin     // 20-bit segment address. Data length must be 2 bytes
26325d7b4fbSAlexey Lapshin     // (4 bytes in hex)
26425d7b4fbSAlexey Lapshin     if (R.HexData.size() != 4)
26525d7b4fbSAlexey Lapshin       return createStringError(
26625d7b4fbSAlexey Lapshin           errc::invalid_argument,
26725d7b4fbSAlexey Lapshin           "segment address data should be 2 bytes in size");
26825d7b4fbSAlexey Lapshin     break;
26925d7b4fbSAlexey Lapshin   case IHexRecord::StartAddr80x86:
27025d7b4fbSAlexey Lapshin   case IHexRecord::StartAddr:
27125d7b4fbSAlexey Lapshin     if (R.HexData.size() != 8)
27225d7b4fbSAlexey Lapshin       return createStringError(errc::invalid_argument,
27325d7b4fbSAlexey Lapshin                                "start address data should be 4 bytes in size");
27425d7b4fbSAlexey Lapshin     // According to Intel HEX specification '03' record
27525d7b4fbSAlexey Lapshin     // only specifies the code address within the 20-bit
27625d7b4fbSAlexey Lapshin     // segmented address space of the 8086/80186. This
27725d7b4fbSAlexey Lapshin     // means 12 high order bits should be zeroes.
27825d7b4fbSAlexey Lapshin     if (R.Type == IHexRecord::StartAddr80x86 &&
27925d7b4fbSAlexey Lapshin         R.HexData.take_front(3) != "000")
28025d7b4fbSAlexey Lapshin       return createStringError(errc::invalid_argument,
28125d7b4fbSAlexey Lapshin                                "start address exceeds 20 bit for 80x86");
28225d7b4fbSAlexey Lapshin     break;
28325d7b4fbSAlexey Lapshin   case IHexRecord::ExtendedAddr:
28425d7b4fbSAlexey Lapshin     // 16-31 bits of linear base address
28525d7b4fbSAlexey Lapshin     if (R.HexData.size() != 4)
28625d7b4fbSAlexey Lapshin       return createStringError(
28725d7b4fbSAlexey Lapshin           errc::invalid_argument,
28825d7b4fbSAlexey Lapshin           "extended address data should be 2 bytes in size");
28925d7b4fbSAlexey Lapshin     break;
29025d7b4fbSAlexey Lapshin   default:
29125d7b4fbSAlexey Lapshin     // Unknown record type
29225d7b4fbSAlexey Lapshin     return createStringError(errc::invalid_argument, "unknown record type: %u",
29325d7b4fbSAlexey Lapshin                              static_cast<unsigned>(R.Type));
29425d7b4fbSAlexey Lapshin   }
29525d7b4fbSAlexey Lapshin   return Error::success();
29625d7b4fbSAlexey Lapshin }
29725d7b4fbSAlexey Lapshin 
29825d7b4fbSAlexey Lapshin // Checks that IHEX line contains valid characters.
29925d7b4fbSAlexey Lapshin // This allows converting hexadecimal data to integers
30025d7b4fbSAlexey Lapshin // without extra verification.
30125d7b4fbSAlexey Lapshin static Error checkChars(StringRef Line) {
30225d7b4fbSAlexey Lapshin   assert(!Line.empty());
30325d7b4fbSAlexey Lapshin   if (Line[0] != ':')
30425d7b4fbSAlexey Lapshin     return createStringError(errc::invalid_argument,
30525d7b4fbSAlexey Lapshin                              "missing ':' in the beginning of line.");
30625d7b4fbSAlexey Lapshin 
30725d7b4fbSAlexey Lapshin   for (size_t Pos = 1; Pos < Line.size(); ++Pos)
30825d7b4fbSAlexey Lapshin     if (hexDigitValue(Line[Pos]) == -1U)
30925d7b4fbSAlexey Lapshin       return createStringError(errc::invalid_argument,
31025d7b4fbSAlexey Lapshin                                "invalid character at position %zu.", Pos + 1);
31125d7b4fbSAlexey Lapshin   return Error::success();
31225d7b4fbSAlexey Lapshin }
31325d7b4fbSAlexey Lapshin 
31425d7b4fbSAlexey Lapshin Expected<IHexRecord> IHexRecord::parse(StringRef Line) {
31525d7b4fbSAlexey Lapshin   assert(!Line.empty());
31625d7b4fbSAlexey Lapshin 
31725d7b4fbSAlexey Lapshin   // ':' + Length + Address + Type + Checksum with empty data ':LLAAAATTCC'
31825d7b4fbSAlexey Lapshin   if (Line.size() < 11)
31925d7b4fbSAlexey Lapshin     return createStringError(errc::invalid_argument,
32025d7b4fbSAlexey Lapshin                              "line is too short: %zu chars.", Line.size());
32125d7b4fbSAlexey Lapshin 
32225d7b4fbSAlexey Lapshin   if (Error E = checkChars(Line))
32325d7b4fbSAlexey Lapshin     return std::move(E);
32425d7b4fbSAlexey Lapshin 
32525d7b4fbSAlexey Lapshin   IHexRecord Rec;
32625d7b4fbSAlexey Lapshin   size_t DataLen = checkedGetHex<uint8_t>(Line.substr(1, 2));
32725d7b4fbSAlexey Lapshin   if (Line.size() != getLength(DataLen))
32825d7b4fbSAlexey Lapshin     return createStringError(errc::invalid_argument,
32925d7b4fbSAlexey Lapshin                              "invalid line length %zu (should be %zu)",
33025d7b4fbSAlexey Lapshin                              Line.size(), getLength(DataLen));
33125d7b4fbSAlexey Lapshin 
33225d7b4fbSAlexey Lapshin   Rec.Addr = checkedGetHex<uint16_t>(Line.substr(3, 4));
33325d7b4fbSAlexey Lapshin   Rec.Type = checkedGetHex<uint8_t>(Line.substr(7, 2));
33425d7b4fbSAlexey Lapshin   Rec.HexData = Line.substr(9, DataLen * 2);
33525d7b4fbSAlexey Lapshin 
33625d7b4fbSAlexey Lapshin   if (getChecksum(Line.drop_front(1)) != 0)
33725d7b4fbSAlexey Lapshin     return createStringError(errc::invalid_argument, "incorrect checksum.");
33825d7b4fbSAlexey Lapshin   if (Error E = checkRecord(Rec))
33925d7b4fbSAlexey Lapshin     return std::move(E);
34025d7b4fbSAlexey Lapshin   return Rec;
34125d7b4fbSAlexey Lapshin }
34225d7b4fbSAlexey Lapshin 
34325d7b4fbSAlexey Lapshin static uint64_t sectionPhysicalAddr(const SectionBase *Sec) {
34425d7b4fbSAlexey Lapshin   Segment *Seg = Sec->ParentSegment;
34525d7b4fbSAlexey Lapshin   if (Seg && Seg->Type != ELF::PT_LOAD)
34625d7b4fbSAlexey Lapshin     Seg = nullptr;
34725d7b4fbSAlexey Lapshin   return Seg ? Seg->PAddr + Sec->OriginalOffset - Seg->OriginalOffset
34825d7b4fbSAlexey Lapshin              : Sec->Addr;
34925d7b4fbSAlexey Lapshin }
35025d7b4fbSAlexey Lapshin 
35125d7b4fbSAlexey Lapshin void IHexSectionWriterBase::writeSection(const SectionBase *Sec,
35225d7b4fbSAlexey Lapshin                                          ArrayRef<uint8_t> Data) {
35325d7b4fbSAlexey Lapshin   assert(Data.size() == Sec->Size);
35425d7b4fbSAlexey Lapshin   const uint32_t ChunkSize = 16;
35525d7b4fbSAlexey Lapshin   uint32_t Addr = sectionPhysicalAddr(Sec) & 0xFFFFFFFFU;
35625d7b4fbSAlexey Lapshin   while (!Data.empty()) {
35725d7b4fbSAlexey Lapshin     uint64_t DataSize = std::min<uint64_t>(Data.size(), ChunkSize);
35825d7b4fbSAlexey Lapshin     if (Addr > SegmentAddr + BaseAddr + 0xFFFFU) {
35925d7b4fbSAlexey Lapshin       if (Addr > 0xFFFFFU) {
36025d7b4fbSAlexey Lapshin         // Write extended address record, zeroing segment address
36125d7b4fbSAlexey Lapshin         // if needed.
36225d7b4fbSAlexey Lapshin         if (SegmentAddr != 0)
36325d7b4fbSAlexey Lapshin           SegmentAddr = writeSegmentAddr(0U);
36425d7b4fbSAlexey Lapshin         BaseAddr = writeBaseAddr(Addr);
36525d7b4fbSAlexey Lapshin       } else {
36625d7b4fbSAlexey Lapshin         // We can still remain 16-bit
36725d7b4fbSAlexey Lapshin         SegmentAddr = writeSegmentAddr(Addr);
36825d7b4fbSAlexey Lapshin       }
36925d7b4fbSAlexey Lapshin     }
37025d7b4fbSAlexey Lapshin     uint64_t SegOffset = Addr - BaseAddr - SegmentAddr;
37125d7b4fbSAlexey Lapshin     assert(SegOffset <= 0xFFFFU);
37225d7b4fbSAlexey Lapshin     DataSize = std::min(DataSize, 0x10000U - SegOffset);
37325d7b4fbSAlexey Lapshin     writeData(0, SegOffset, Data.take_front(DataSize));
37425d7b4fbSAlexey Lapshin     Addr += DataSize;
37525d7b4fbSAlexey Lapshin     Data = Data.drop_front(DataSize);
37625d7b4fbSAlexey Lapshin   }
37725d7b4fbSAlexey Lapshin }
37825d7b4fbSAlexey Lapshin 
37925d7b4fbSAlexey Lapshin uint64_t IHexSectionWriterBase::writeSegmentAddr(uint64_t Addr) {
38025d7b4fbSAlexey Lapshin   assert(Addr <= 0xFFFFFU);
38125d7b4fbSAlexey Lapshin   uint8_t Data[] = {static_cast<uint8_t>((Addr & 0xF0000U) >> 12), 0};
38225d7b4fbSAlexey Lapshin   writeData(2, 0, Data);
38325d7b4fbSAlexey Lapshin   return Addr & 0xF0000U;
38425d7b4fbSAlexey Lapshin }
38525d7b4fbSAlexey Lapshin 
38625d7b4fbSAlexey Lapshin uint64_t IHexSectionWriterBase::writeBaseAddr(uint64_t Addr) {
38725d7b4fbSAlexey Lapshin   assert(Addr <= 0xFFFFFFFFU);
38825d7b4fbSAlexey Lapshin   uint64_t Base = Addr & 0xFFFF0000U;
38925d7b4fbSAlexey Lapshin   uint8_t Data[] = {static_cast<uint8_t>(Base >> 24),
39025d7b4fbSAlexey Lapshin                     static_cast<uint8_t>((Base >> 16) & 0xFF)};
39125d7b4fbSAlexey Lapshin   writeData(4, 0, Data);
39225d7b4fbSAlexey Lapshin   return Base;
39325d7b4fbSAlexey Lapshin }
39425d7b4fbSAlexey Lapshin 
39525d7b4fbSAlexey Lapshin void IHexSectionWriterBase::writeData(uint8_t, uint16_t,
39625d7b4fbSAlexey Lapshin                                       ArrayRef<uint8_t> Data) {
39725d7b4fbSAlexey Lapshin   Offset += IHexRecord::getLineLength(Data.size());
39825d7b4fbSAlexey Lapshin }
39925d7b4fbSAlexey Lapshin 
40025d7b4fbSAlexey Lapshin Error IHexSectionWriterBase::visit(const Section &Sec) {
40125d7b4fbSAlexey Lapshin   writeSection(&Sec, Sec.Contents);
40225d7b4fbSAlexey Lapshin   return Error::success();
40325d7b4fbSAlexey Lapshin }
40425d7b4fbSAlexey Lapshin 
40525d7b4fbSAlexey Lapshin Error IHexSectionWriterBase::visit(const OwnedDataSection &Sec) {
40625d7b4fbSAlexey Lapshin   writeSection(&Sec, Sec.Data);
40725d7b4fbSAlexey Lapshin   return Error::success();
40825d7b4fbSAlexey Lapshin }
40925d7b4fbSAlexey Lapshin 
41025d7b4fbSAlexey Lapshin Error IHexSectionWriterBase::visit(const StringTableSection &Sec) {
41125d7b4fbSAlexey Lapshin   // Check that sizer has already done its work
41225d7b4fbSAlexey Lapshin   assert(Sec.Size == Sec.StrTabBuilder.getSize());
41325d7b4fbSAlexey Lapshin   // We are free to pass an invalid pointer to writeSection as long
41425d7b4fbSAlexey Lapshin   // as we don't actually write any data. The real writer class has
41525d7b4fbSAlexey Lapshin   // to override this method .
41625d7b4fbSAlexey Lapshin   writeSection(&Sec, {nullptr, static_cast<size_t>(Sec.Size)});
41725d7b4fbSAlexey Lapshin   return Error::success();
41825d7b4fbSAlexey Lapshin }
41925d7b4fbSAlexey Lapshin 
42025d7b4fbSAlexey Lapshin Error IHexSectionWriterBase::visit(const DynamicRelocationSection &Sec) {
42125d7b4fbSAlexey Lapshin   writeSection(&Sec, Sec.Contents);
42225d7b4fbSAlexey Lapshin   return Error::success();
42325d7b4fbSAlexey Lapshin }
42425d7b4fbSAlexey Lapshin 
42525d7b4fbSAlexey Lapshin void IHexSectionWriter::writeData(uint8_t Type, uint16_t Addr,
42625d7b4fbSAlexey Lapshin                                   ArrayRef<uint8_t> Data) {
42725d7b4fbSAlexey Lapshin   IHexLineData HexData = IHexRecord::getLine(Type, Addr, Data);
42825d7b4fbSAlexey Lapshin   memcpy(Out.getBufferStart() + Offset, HexData.data(), HexData.size());
42925d7b4fbSAlexey Lapshin   Offset += HexData.size();
43025d7b4fbSAlexey Lapshin }
43125d7b4fbSAlexey Lapshin 
43225d7b4fbSAlexey Lapshin Error IHexSectionWriter::visit(const StringTableSection &Sec) {
43325d7b4fbSAlexey Lapshin   assert(Sec.Size == Sec.StrTabBuilder.getSize());
43425d7b4fbSAlexey Lapshin   std::vector<uint8_t> Data(Sec.Size);
43525d7b4fbSAlexey Lapshin   Sec.StrTabBuilder.write(Data.data());
43625d7b4fbSAlexey Lapshin   writeSection(&Sec, Data);
43725d7b4fbSAlexey Lapshin   return Error::success();
43825d7b4fbSAlexey Lapshin }
43925d7b4fbSAlexey Lapshin 
44025d7b4fbSAlexey Lapshin Error Section::accept(SectionVisitor &Visitor) const {
44125d7b4fbSAlexey Lapshin   return Visitor.visit(*this);
44225d7b4fbSAlexey Lapshin }
44325d7b4fbSAlexey Lapshin 
44425d7b4fbSAlexey Lapshin Error Section::accept(MutableSectionVisitor &Visitor) {
44525d7b4fbSAlexey Lapshin   return Visitor.visit(*this);
44625d7b4fbSAlexey Lapshin }
44725d7b4fbSAlexey Lapshin 
448744e589cSAndrew Ng void Section::restoreSymTabLink(SymbolTableSection &SymTab) {
449744e589cSAndrew Ng   if (HasSymTabLink) {
450744e589cSAndrew Ng     assert(LinkSection == nullptr);
451744e589cSAndrew Ng     LinkSection = &SymTab;
452744e589cSAndrew Ng   }
453744e589cSAndrew Ng }
454744e589cSAndrew Ng 
45525d7b4fbSAlexey Lapshin Error SectionWriter::visit(const OwnedDataSection &Sec) {
45625d7b4fbSAlexey Lapshin   llvm::copy(Sec.Data, Out.getBufferStart() + Sec.Offset);
45725d7b4fbSAlexey Lapshin   return Error::success();
45825d7b4fbSAlexey Lapshin }
45925d7b4fbSAlexey Lapshin 
46025d7b4fbSAlexey Lapshin template <class ELFT>
46125d7b4fbSAlexey Lapshin Error ELFSectionWriter<ELFT>::visit(const DecompressedSection &Sec) {
46273c84f9cSFangrui Song   ArrayRef<uint8_t> Compressed =
46373c84f9cSFangrui Song       Sec.OriginalData.slice(sizeof(Elf_Chdr_Impl<ELFT>));
464b6e1fd76SFangrui Song   SmallVector<uint8_t, 128> Decompressed;
465b6e1fd76SFangrui Song   DebugCompressionType Type;
466b6e1fd76SFangrui Song   switch (Sec.ChType) {
467b6e1fd76SFangrui Song   case ELFCOMPRESS_ZLIB:
468781dea02SFangrui Song     Type = DebugCompressionType::Zlib;
469b6e1fd76SFangrui Song     break;
470b6e1fd76SFangrui Song   case ELFCOMPRESS_ZSTD:
471b6e1fd76SFangrui Song     Type = DebugCompressionType::Zstd;
472b6e1fd76SFangrui Song     break;
473b6e1fd76SFangrui Song   default:
474b6e1fd76SFangrui Song     return createStringError(errc::invalid_argument,
475b6e1fd76SFangrui Song                              "--decompress-debug-sections: ch_type (" +
476b6e1fd76SFangrui Song                                  Twine(Sec.ChType) + ") of section '" +
477b6e1fd76SFangrui Song                                  Sec.Name + "' is unsupported");
478b6e1fd76SFangrui Song   }
479e18b7c7aSFangrui Song   if (auto *Reason =
480e18b7c7aSFangrui Song           compression::getReasonIfUnsupported(compression::formatFor(Type)))
481e18b7c7aSFangrui Song     return createStringError(errc::invalid_argument,
482e18b7c7aSFangrui Song                              "failed to decompress section '" + Sec.Name +
483e18b7c7aSFangrui Song                                  "': " + Reason);
484b6e1fd76SFangrui Song   if (Error E = compression::decompress(Type, Compressed, Decompressed,
485c26dc290SFangrui Song                                         static_cast<size_t>(Sec.Size)))
486c26dc290SFangrui Song     return createStringError(errc::invalid_argument,
487b6e1fd76SFangrui Song                              "failed to decompress section '" + Sec.Name +
488b6e1fd76SFangrui Song                                  "': " + toString(std::move(E)));
48925d7b4fbSAlexey Lapshin 
49025d7b4fbSAlexey Lapshin   uint8_t *Buf = reinterpret_cast<uint8_t *>(Out.getBufferStart()) + Sec.Offset;
491b6e1fd76SFangrui Song   std::copy(Decompressed.begin(), Decompressed.end(), Buf);
49225d7b4fbSAlexey Lapshin 
49325d7b4fbSAlexey Lapshin   return Error::success();
49425d7b4fbSAlexey Lapshin }
49525d7b4fbSAlexey Lapshin 
49625d7b4fbSAlexey Lapshin Error BinarySectionWriter::visit(const DecompressedSection &Sec) {
49725d7b4fbSAlexey Lapshin   return createStringError(errc::operation_not_permitted,
49825d7b4fbSAlexey Lapshin                            "cannot write compressed section '" + Sec.Name +
49925d7b4fbSAlexey Lapshin                                "' ");
50025d7b4fbSAlexey Lapshin }
50125d7b4fbSAlexey Lapshin 
50225d7b4fbSAlexey Lapshin Error DecompressedSection::accept(SectionVisitor &Visitor) const {
50325d7b4fbSAlexey Lapshin   return Visitor.visit(*this);
50425d7b4fbSAlexey Lapshin }
50525d7b4fbSAlexey Lapshin 
50625d7b4fbSAlexey Lapshin Error DecompressedSection::accept(MutableSectionVisitor &Visitor) {
50725d7b4fbSAlexey Lapshin   return Visitor.visit(*this);
50825d7b4fbSAlexey Lapshin }
50925d7b4fbSAlexey Lapshin 
51025d7b4fbSAlexey Lapshin Error OwnedDataSection::accept(SectionVisitor &Visitor) const {
51125d7b4fbSAlexey Lapshin   return Visitor.visit(*this);
51225d7b4fbSAlexey Lapshin }
51325d7b4fbSAlexey Lapshin 
51425d7b4fbSAlexey Lapshin Error OwnedDataSection::accept(MutableSectionVisitor &Visitor) {
51525d7b4fbSAlexey Lapshin   return Visitor.visit(*this);
51625d7b4fbSAlexey Lapshin }
51725d7b4fbSAlexey Lapshin 
51825d7b4fbSAlexey Lapshin void OwnedDataSection::appendHexData(StringRef HexData) {
51925d7b4fbSAlexey Lapshin   assert((HexData.size() & 1) == 0);
52025d7b4fbSAlexey Lapshin   while (!HexData.empty()) {
52125d7b4fbSAlexey Lapshin     Data.push_back(checkedGetHex<uint8_t>(HexData.take_front(2)));
52225d7b4fbSAlexey Lapshin     HexData = HexData.drop_front(2);
52325d7b4fbSAlexey Lapshin   }
52425d7b4fbSAlexey Lapshin   Size = Data.size();
52525d7b4fbSAlexey Lapshin }
52625d7b4fbSAlexey Lapshin 
52725d7b4fbSAlexey Lapshin Error BinarySectionWriter::visit(const CompressedSection &Sec) {
52825d7b4fbSAlexey Lapshin   return createStringError(errc::operation_not_permitted,
52925d7b4fbSAlexey Lapshin                            "cannot write compressed section '" + Sec.Name +
53025d7b4fbSAlexey Lapshin                                "' ");
53125d7b4fbSAlexey Lapshin }
53225d7b4fbSAlexey Lapshin 
53325d7b4fbSAlexey Lapshin template <class ELFT>
53425d7b4fbSAlexey Lapshin Error ELFSectionWriter<ELFT>::visit(const CompressedSection &Sec) {
53525d7b4fbSAlexey Lapshin   uint8_t *Buf = reinterpret_cast<uint8_t *>(Out.getBufferStart()) + Sec.Offset;
5367181c4e1SFangrui Song   Elf_Chdr_Impl<ELFT> Chdr = {};
53745ae5531SFangrui Song   switch (Sec.CompressionType) {
53845ae5531SFangrui Song   case DebugCompressionType::None:
53925d7b4fbSAlexey Lapshin     std::copy(Sec.OriginalData.begin(), Sec.OriginalData.end(), Buf);
54025d7b4fbSAlexey Lapshin     return Error::success();
541781dea02SFangrui Song   case DebugCompressionType::Zlib:
54225d7b4fbSAlexey Lapshin     Chdr.ch_type = ELF::ELFCOMPRESS_ZLIB;
54345ae5531SFangrui Song     break;
544b6e1fd76SFangrui Song   case DebugCompressionType::Zstd:
545b6e1fd76SFangrui Song     Chdr.ch_type = ELF::ELFCOMPRESS_ZSTD;
546b6e1fd76SFangrui Song     break;
54745ae5531SFangrui Song   }
54825d7b4fbSAlexey Lapshin   Chdr.ch_size = Sec.DecompressedSize;
54925d7b4fbSAlexey Lapshin   Chdr.ch_addralign = Sec.DecompressedAlign;
55025d7b4fbSAlexey Lapshin   memcpy(Buf, &Chdr, sizeof(Chdr));
55125d7b4fbSAlexey Lapshin   Buf += sizeof(Chdr);
55225d7b4fbSAlexey Lapshin 
55325d7b4fbSAlexey Lapshin   std::copy(Sec.CompressedData.begin(), Sec.CompressedData.end(), Buf);
55425d7b4fbSAlexey Lapshin   return Error::success();
55525d7b4fbSAlexey Lapshin }
55625d7b4fbSAlexey Lapshin 
55725d7b4fbSAlexey Lapshin CompressedSection::CompressedSection(const SectionBase &Sec,
558c997fe65SFangrui Song                                      DebugCompressionType CompressionType,
559c997fe65SFangrui Song                                      bool Is64Bits)
56025d7b4fbSAlexey Lapshin     : SectionBase(Sec), CompressionType(CompressionType),
56125d7b4fbSAlexey Lapshin       DecompressedSize(Sec.OriginalData.size()), DecompressedAlign(Sec.Align) {
562b6e1fd76SFangrui Song   compression::compress(compression::Params(CompressionType), OriginalData,
563b6e1fd76SFangrui Song                         CompressedData);
56425d7b4fbSAlexey Lapshin 
56525d7b4fbSAlexey Lapshin   Flags |= ELF::SHF_COMPRESSED;
56607942987SFangrui Song   OriginalFlags |= ELF::SHF_COMPRESSED;
567c997fe65SFangrui Song   size_t ChdrSize = Is64Bits ? sizeof(object::Elf_Chdr_Impl<object::ELF64LE>)
568c997fe65SFangrui Song                              : sizeof(object::Elf_Chdr_Impl<object::ELF32LE>);
56925d7b4fbSAlexey Lapshin   Size = ChdrSize + CompressedData.size();
57025d7b4fbSAlexey Lapshin   Align = 8;
57125d7b4fbSAlexey Lapshin }
57225d7b4fbSAlexey Lapshin 
57325d7b4fbSAlexey Lapshin CompressedSection::CompressedSection(ArrayRef<uint8_t> CompressedData,
574b6e1fd76SFangrui Song                                      uint32_t ChType, uint64_t DecompressedSize,
57525d7b4fbSAlexey Lapshin                                      uint64_t DecompressedAlign)
576b6e1fd76SFangrui Song     : ChType(ChType), CompressionType(DebugCompressionType::None),
57725d7b4fbSAlexey Lapshin       DecompressedSize(DecompressedSize), DecompressedAlign(DecompressedAlign) {
57825d7b4fbSAlexey Lapshin   OriginalData = CompressedData;
57925d7b4fbSAlexey Lapshin }
58025d7b4fbSAlexey Lapshin 
58125d7b4fbSAlexey Lapshin Error CompressedSection::accept(SectionVisitor &Visitor) const {
58225d7b4fbSAlexey Lapshin   return Visitor.visit(*this);
58325d7b4fbSAlexey Lapshin }
58425d7b4fbSAlexey Lapshin 
58525d7b4fbSAlexey Lapshin Error CompressedSection::accept(MutableSectionVisitor &Visitor) {
58625d7b4fbSAlexey Lapshin   return Visitor.visit(*this);
58725d7b4fbSAlexey Lapshin }
58825d7b4fbSAlexey Lapshin 
58925d7b4fbSAlexey Lapshin void StringTableSection::addString(StringRef Name) { StrTabBuilder.add(Name); }
59025d7b4fbSAlexey Lapshin 
59125d7b4fbSAlexey Lapshin uint32_t StringTableSection::findIndex(StringRef Name) const {
59225d7b4fbSAlexey Lapshin   return StrTabBuilder.getOffset(Name);
59325d7b4fbSAlexey Lapshin }
59425d7b4fbSAlexey Lapshin 
59525d7b4fbSAlexey Lapshin void StringTableSection::prepareForLayout() {
59625d7b4fbSAlexey Lapshin   StrTabBuilder.finalize();
59725d7b4fbSAlexey Lapshin   Size = StrTabBuilder.getSize();
59825d7b4fbSAlexey Lapshin }
59925d7b4fbSAlexey Lapshin 
60025d7b4fbSAlexey Lapshin Error SectionWriter::visit(const StringTableSection &Sec) {
60125d7b4fbSAlexey Lapshin   Sec.StrTabBuilder.write(reinterpret_cast<uint8_t *>(Out.getBufferStart()) +
60225d7b4fbSAlexey Lapshin                           Sec.Offset);
60325d7b4fbSAlexey Lapshin   return Error::success();
60425d7b4fbSAlexey Lapshin }
60525d7b4fbSAlexey Lapshin 
60625d7b4fbSAlexey Lapshin Error StringTableSection::accept(SectionVisitor &Visitor) const {
60725d7b4fbSAlexey Lapshin   return Visitor.visit(*this);
60825d7b4fbSAlexey Lapshin }
60925d7b4fbSAlexey Lapshin 
61025d7b4fbSAlexey Lapshin Error StringTableSection::accept(MutableSectionVisitor &Visitor) {
61125d7b4fbSAlexey Lapshin   return Visitor.visit(*this);
61225d7b4fbSAlexey Lapshin }
61325d7b4fbSAlexey Lapshin 
61425d7b4fbSAlexey Lapshin template <class ELFT>
61525d7b4fbSAlexey Lapshin Error ELFSectionWriter<ELFT>::visit(const SectionIndexSection &Sec) {
61625d7b4fbSAlexey Lapshin   uint8_t *Buf = reinterpret_cast<uint8_t *>(Out.getBufferStart()) + Sec.Offset;
61725d7b4fbSAlexey Lapshin   llvm::copy(Sec.Indexes, reinterpret_cast<Elf_Word *>(Buf));
61825d7b4fbSAlexey Lapshin   return Error::success();
61925d7b4fbSAlexey Lapshin }
62025d7b4fbSAlexey Lapshin 
62125d7b4fbSAlexey Lapshin Error SectionIndexSection::initialize(SectionTableRef SecTable) {
62225d7b4fbSAlexey Lapshin   Size = 0;
62325d7b4fbSAlexey Lapshin   Expected<SymbolTableSection *> Sec =
62425d7b4fbSAlexey Lapshin       SecTable.getSectionOfType<SymbolTableSection>(
62525d7b4fbSAlexey Lapshin           Link,
62625d7b4fbSAlexey Lapshin           "Link field value " + Twine(Link) + " in section " + Name +
62725d7b4fbSAlexey Lapshin               " is invalid",
62825d7b4fbSAlexey Lapshin           "Link field value " + Twine(Link) + " in section " + Name +
62925d7b4fbSAlexey Lapshin               " is not a symbol table");
63025d7b4fbSAlexey Lapshin   if (!Sec)
63125d7b4fbSAlexey Lapshin     return Sec.takeError();
63225d7b4fbSAlexey Lapshin 
63325d7b4fbSAlexey Lapshin   setSymTab(*Sec);
63425d7b4fbSAlexey Lapshin   Symbols->setShndxTable(this);
63525d7b4fbSAlexey Lapshin   return Error::success();
63625d7b4fbSAlexey Lapshin }
63725d7b4fbSAlexey Lapshin 
63825d7b4fbSAlexey Lapshin void SectionIndexSection::finalize() { Link = Symbols->Index; }
63925d7b4fbSAlexey Lapshin 
64025d7b4fbSAlexey Lapshin Error SectionIndexSection::accept(SectionVisitor &Visitor) const {
64125d7b4fbSAlexey Lapshin   return Visitor.visit(*this);
64225d7b4fbSAlexey Lapshin }
64325d7b4fbSAlexey Lapshin 
64425d7b4fbSAlexey Lapshin Error SectionIndexSection::accept(MutableSectionVisitor &Visitor) {
64525d7b4fbSAlexey Lapshin   return Visitor.visit(*this);
64625d7b4fbSAlexey Lapshin }
64725d7b4fbSAlexey Lapshin 
64825d7b4fbSAlexey Lapshin static bool isValidReservedSectionIndex(uint16_t Index, uint16_t Machine) {
64925d7b4fbSAlexey Lapshin   switch (Index) {
65025d7b4fbSAlexey Lapshin   case SHN_ABS:
65125d7b4fbSAlexey Lapshin   case SHN_COMMON:
65225d7b4fbSAlexey Lapshin     return true;
65325d7b4fbSAlexey Lapshin   }
65425d7b4fbSAlexey Lapshin 
65525d7b4fbSAlexey Lapshin   if (Machine == EM_AMDGPU) {
65625d7b4fbSAlexey Lapshin     return Index == SHN_AMDGPU_LDS;
65725d7b4fbSAlexey Lapshin   }
65825d7b4fbSAlexey Lapshin 
6599da89651SAnubhab Ghosh   if (Machine == EM_MIPS) {
6609da89651SAnubhab Ghosh     switch (Index) {
6619da89651SAnubhab Ghosh     case SHN_MIPS_ACOMMON:
6629da89651SAnubhab Ghosh     case SHN_MIPS_SCOMMON:
6639da89651SAnubhab Ghosh     case SHN_MIPS_SUNDEFINED:
6649da89651SAnubhab Ghosh       return true;
6659da89651SAnubhab Ghosh     }
6669da89651SAnubhab Ghosh   }
6679da89651SAnubhab Ghosh 
66825d7b4fbSAlexey Lapshin   if (Machine == EM_HEXAGON) {
66925d7b4fbSAlexey Lapshin     switch (Index) {
67025d7b4fbSAlexey Lapshin     case SHN_HEXAGON_SCOMMON:
67125d7b4fbSAlexey Lapshin     case SHN_HEXAGON_SCOMMON_1:
67225d7b4fbSAlexey Lapshin     case SHN_HEXAGON_SCOMMON_2:
67325d7b4fbSAlexey Lapshin     case SHN_HEXAGON_SCOMMON_4:
67425d7b4fbSAlexey Lapshin     case SHN_HEXAGON_SCOMMON_8:
67525d7b4fbSAlexey Lapshin       return true;
67625d7b4fbSAlexey Lapshin     }
67725d7b4fbSAlexey Lapshin   }
67825d7b4fbSAlexey Lapshin   return false;
67925d7b4fbSAlexey Lapshin }
68025d7b4fbSAlexey Lapshin 
68125d7b4fbSAlexey Lapshin // Large indexes force us to clarify exactly what this function should do. This
68225d7b4fbSAlexey Lapshin // function should return the value that will appear in st_shndx when written
68325d7b4fbSAlexey Lapshin // out.
68425d7b4fbSAlexey Lapshin uint16_t Symbol::getShndx() const {
68525d7b4fbSAlexey Lapshin   if (DefinedIn != nullptr) {
68625d7b4fbSAlexey Lapshin     if (DefinedIn->Index >= SHN_LORESERVE)
68725d7b4fbSAlexey Lapshin       return SHN_XINDEX;
68825d7b4fbSAlexey Lapshin     return DefinedIn->Index;
68925d7b4fbSAlexey Lapshin   }
69025d7b4fbSAlexey Lapshin 
69125d7b4fbSAlexey Lapshin   if (ShndxType == SYMBOL_SIMPLE_INDEX) {
69225d7b4fbSAlexey Lapshin     // This means that we don't have a defined section but we do need to
69325d7b4fbSAlexey Lapshin     // output a legitimate section index.
69425d7b4fbSAlexey Lapshin     return SHN_UNDEF;
69525d7b4fbSAlexey Lapshin   }
69625d7b4fbSAlexey Lapshin 
69725d7b4fbSAlexey Lapshin   assert(ShndxType == SYMBOL_ABS || ShndxType == SYMBOL_COMMON ||
69825d7b4fbSAlexey Lapshin          (ShndxType >= SYMBOL_LOPROC && ShndxType <= SYMBOL_HIPROC) ||
69925d7b4fbSAlexey Lapshin          (ShndxType >= SYMBOL_LOOS && ShndxType <= SYMBOL_HIOS));
70025d7b4fbSAlexey Lapshin   return static_cast<uint16_t>(ShndxType);
70125d7b4fbSAlexey Lapshin }
70225d7b4fbSAlexey Lapshin 
70325d7b4fbSAlexey Lapshin bool Symbol::isCommon() const { return getShndx() == SHN_COMMON; }
70425d7b4fbSAlexey Lapshin 
70525d7b4fbSAlexey Lapshin void SymbolTableSection::assignIndices() {
70625d7b4fbSAlexey Lapshin   uint32_t Index = 0;
707744e589cSAndrew Ng   for (auto &Sym : Symbols) {
708744e589cSAndrew Ng     if (Sym->Index != Index)
709744e589cSAndrew Ng       IndicesChanged = true;
71025d7b4fbSAlexey Lapshin     Sym->Index = Index++;
71125d7b4fbSAlexey Lapshin   }
712744e589cSAndrew Ng }
71325d7b4fbSAlexey Lapshin 
71425d7b4fbSAlexey Lapshin void SymbolTableSection::addSymbol(Twine Name, uint8_t Bind, uint8_t Type,
71525d7b4fbSAlexey Lapshin                                    SectionBase *DefinedIn, uint64_t Value,
71625d7b4fbSAlexey Lapshin                                    uint8_t Visibility, uint16_t Shndx,
71725d7b4fbSAlexey Lapshin                                    uint64_t SymbolSize) {
71825d7b4fbSAlexey Lapshin   Symbol Sym;
71925d7b4fbSAlexey Lapshin   Sym.Name = Name.str();
72025d7b4fbSAlexey Lapshin   Sym.Binding = Bind;
72125d7b4fbSAlexey Lapshin   Sym.Type = Type;
72225d7b4fbSAlexey Lapshin   Sym.DefinedIn = DefinedIn;
72325d7b4fbSAlexey Lapshin   if (DefinedIn != nullptr)
72425d7b4fbSAlexey Lapshin     DefinedIn->HasSymbol = true;
72525d7b4fbSAlexey Lapshin   if (DefinedIn == nullptr) {
72625d7b4fbSAlexey Lapshin     if (Shndx >= SHN_LORESERVE)
72725d7b4fbSAlexey Lapshin       Sym.ShndxType = static_cast<SymbolShndxType>(Shndx);
72825d7b4fbSAlexey Lapshin     else
72925d7b4fbSAlexey Lapshin       Sym.ShndxType = SYMBOL_SIMPLE_INDEX;
73025d7b4fbSAlexey Lapshin   }
73125d7b4fbSAlexey Lapshin   Sym.Value = Value;
73225d7b4fbSAlexey Lapshin   Sym.Visibility = Visibility;
73325d7b4fbSAlexey Lapshin   Sym.Size = SymbolSize;
73425d7b4fbSAlexey Lapshin   Sym.Index = Symbols.size();
73525d7b4fbSAlexey Lapshin   Symbols.emplace_back(std::make_unique<Symbol>(Sym));
73625d7b4fbSAlexey Lapshin   Size += this->EntrySize;
73725d7b4fbSAlexey Lapshin }
73825d7b4fbSAlexey Lapshin 
73925d7b4fbSAlexey Lapshin Error SymbolTableSection::removeSectionReferences(
74025d7b4fbSAlexey Lapshin     bool AllowBrokenLinks, function_ref<bool(const SectionBase *)> ToRemove) {
74125d7b4fbSAlexey Lapshin   if (ToRemove(SectionIndexTable))
74225d7b4fbSAlexey Lapshin     SectionIndexTable = nullptr;
74325d7b4fbSAlexey Lapshin   if (ToRemove(SymbolNames)) {
74425d7b4fbSAlexey Lapshin     if (!AllowBrokenLinks)
74525d7b4fbSAlexey Lapshin       return createStringError(
74625d7b4fbSAlexey Lapshin           llvm::errc::invalid_argument,
74725d7b4fbSAlexey Lapshin           "string table '%s' cannot be removed because it is "
74825d7b4fbSAlexey Lapshin           "referenced by the symbol table '%s'",
74925d7b4fbSAlexey Lapshin           SymbolNames->Name.data(), this->Name.data());
75025d7b4fbSAlexey Lapshin     SymbolNames = nullptr;
75125d7b4fbSAlexey Lapshin   }
75225d7b4fbSAlexey Lapshin   return removeSymbols(
75325d7b4fbSAlexey Lapshin       [ToRemove](const Symbol &Sym) { return ToRemove(Sym.DefinedIn); });
75425d7b4fbSAlexey Lapshin }
75525d7b4fbSAlexey Lapshin 
75625d7b4fbSAlexey Lapshin void SymbolTableSection::updateSymbols(function_ref<void(Symbol &)> Callable) {
7573b9707dbSKazu Hirata   for (SymPtr &Sym : llvm::drop_begin(Symbols))
7583b9707dbSKazu Hirata     Callable(*Sym);
75925d7b4fbSAlexey Lapshin   std::stable_partition(
76025d7b4fbSAlexey Lapshin       std::begin(Symbols), std::end(Symbols),
76125d7b4fbSAlexey Lapshin       [](const SymPtr &Sym) { return Sym->Binding == STB_LOCAL; });
76225d7b4fbSAlexey Lapshin   assignIndices();
76325d7b4fbSAlexey Lapshin }
76425d7b4fbSAlexey Lapshin 
76525d7b4fbSAlexey Lapshin Error SymbolTableSection::removeSymbols(
76625d7b4fbSAlexey Lapshin     function_ref<bool(const Symbol &)> ToRemove) {
76725d7b4fbSAlexey Lapshin   Symbols.erase(
76825d7b4fbSAlexey Lapshin       std::remove_if(std::begin(Symbols) + 1, std::end(Symbols),
76925d7b4fbSAlexey Lapshin                      [ToRemove](const SymPtr &Sym) { return ToRemove(*Sym); }),
77025d7b4fbSAlexey Lapshin       std::end(Symbols));
771744e589cSAndrew Ng   auto PrevSize = Size;
77225d7b4fbSAlexey Lapshin   Size = Symbols.size() * EntrySize;
773744e589cSAndrew Ng   if (Size < PrevSize)
774744e589cSAndrew Ng     IndicesChanged = true;
77525d7b4fbSAlexey Lapshin   assignIndices();
77625d7b4fbSAlexey Lapshin   return Error::success();
77725d7b4fbSAlexey Lapshin }
77825d7b4fbSAlexey Lapshin 
77925d7b4fbSAlexey Lapshin void SymbolTableSection::replaceSectionReferences(
78025d7b4fbSAlexey Lapshin     const DenseMap<SectionBase *, SectionBase *> &FromTo) {
78125d7b4fbSAlexey Lapshin   for (std::unique_ptr<Symbol> &Sym : Symbols)
78225d7b4fbSAlexey Lapshin     if (SectionBase *To = FromTo.lookup(Sym->DefinedIn))
78325d7b4fbSAlexey Lapshin       Sym->DefinedIn = To;
78425d7b4fbSAlexey Lapshin }
78525d7b4fbSAlexey Lapshin 
78625d7b4fbSAlexey Lapshin Error SymbolTableSection::initialize(SectionTableRef SecTable) {
78725d7b4fbSAlexey Lapshin   Size = 0;
78825d7b4fbSAlexey Lapshin   Expected<StringTableSection *> Sec =
78925d7b4fbSAlexey Lapshin       SecTable.getSectionOfType<StringTableSection>(
79025d7b4fbSAlexey Lapshin           Link,
79125d7b4fbSAlexey Lapshin           "Symbol table has link index of " + Twine(Link) +
79225d7b4fbSAlexey Lapshin               " which is not a valid index",
79325d7b4fbSAlexey Lapshin           "Symbol table has link index of " + Twine(Link) +
79425d7b4fbSAlexey Lapshin               " which is not a string table");
79525d7b4fbSAlexey Lapshin   if (!Sec)
79625d7b4fbSAlexey Lapshin     return Sec.takeError();
79725d7b4fbSAlexey Lapshin 
79825d7b4fbSAlexey Lapshin   setStrTab(*Sec);
79925d7b4fbSAlexey Lapshin   return Error::success();
80025d7b4fbSAlexey Lapshin }
80125d7b4fbSAlexey Lapshin 
80225d7b4fbSAlexey Lapshin void SymbolTableSection::finalize() {
80325d7b4fbSAlexey Lapshin   uint32_t MaxLocalIndex = 0;
80425d7b4fbSAlexey Lapshin   for (std::unique_ptr<Symbol> &Sym : Symbols) {
80525d7b4fbSAlexey Lapshin     Sym->NameIndex =
80625d7b4fbSAlexey Lapshin         SymbolNames == nullptr ? 0 : SymbolNames->findIndex(Sym->Name);
80725d7b4fbSAlexey Lapshin     if (Sym->Binding == STB_LOCAL)
80825d7b4fbSAlexey Lapshin       MaxLocalIndex = std::max(MaxLocalIndex, Sym->Index);
80925d7b4fbSAlexey Lapshin   }
81025d7b4fbSAlexey Lapshin   // Now we need to set the Link and Info fields.
81125d7b4fbSAlexey Lapshin   Link = SymbolNames == nullptr ? 0 : SymbolNames->Index;
81225d7b4fbSAlexey Lapshin   Info = MaxLocalIndex + 1;
81325d7b4fbSAlexey Lapshin }
81425d7b4fbSAlexey Lapshin 
81525d7b4fbSAlexey Lapshin void SymbolTableSection::prepareForLayout() {
81625d7b4fbSAlexey Lapshin   // Reserve proper amount of space in section index table, so we can
81725d7b4fbSAlexey Lapshin   // layout sections correctly. We will fill the table with correct
81825d7b4fbSAlexey Lapshin   // indexes later in fillShdnxTable.
81925d7b4fbSAlexey Lapshin   if (SectionIndexTable)
82025d7b4fbSAlexey Lapshin     SectionIndexTable->reserve(Symbols.size());
82125d7b4fbSAlexey Lapshin 
82225d7b4fbSAlexey Lapshin   // Add all of our strings to SymbolNames so that SymbolNames has the right
82325d7b4fbSAlexey Lapshin   // size before layout is decided.
82425d7b4fbSAlexey Lapshin   // If the symbol names section has been removed, don't try to add strings to
82525d7b4fbSAlexey Lapshin   // the table.
82625d7b4fbSAlexey Lapshin   if (SymbolNames != nullptr)
82725d7b4fbSAlexey Lapshin     for (std::unique_ptr<Symbol> &Sym : Symbols)
82825d7b4fbSAlexey Lapshin       SymbolNames->addString(Sym->Name);
82925d7b4fbSAlexey Lapshin }
83025d7b4fbSAlexey Lapshin 
83125d7b4fbSAlexey Lapshin void SymbolTableSection::fillShndxTable() {
83225d7b4fbSAlexey Lapshin   if (SectionIndexTable == nullptr)
83325d7b4fbSAlexey Lapshin     return;
83425d7b4fbSAlexey Lapshin   // Fill section index table with real section indexes. This function must
83525d7b4fbSAlexey Lapshin   // be called after assignOffsets.
83625d7b4fbSAlexey Lapshin   for (const std::unique_ptr<Symbol> &Sym : Symbols) {
83725d7b4fbSAlexey Lapshin     if (Sym->DefinedIn != nullptr && Sym->DefinedIn->Index >= SHN_LORESERVE)
83825d7b4fbSAlexey Lapshin       SectionIndexTable->addIndex(Sym->DefinedIn->Index);
83925d7b4fbSAlexey Lapshin     else
84025d7b4fbSAlexey Lapshin       SectionIndexTable->addIndex(SHN_UNDEF);
84125d7b4fbSAlexey Lapshin   }
84225d7b4fbSAlexey Lapshin }
84325d7b4fbSAlexey Lapshin 
84425d7b4fbSAlexey Lapshin Expected<const Symbol *>
84525d7b4fbSAlexey Lapshin SymbolTableSection::getSymbolByIndex(uint32_t Index) const {
84625d7b4fbSAlexey Lapshin   if (Symbols.size() <= Index)
84725d7b4fbSAlexey Lapshin     return createStringError(errc::invalid_argument,
84825d7b4fbSAlexey Lapshin                              "invalid symbol index: " + Twine(Index));
84925d7b4fbSAlexey Lapshin   return Symbols[Index].get();
85025d7b4fbSAlexey Lapshin }
85125d7b4fbSAlexey Lapshin 
85225d7b4fbSAlexey Lapshin Expected<Symbol *> SymbolTableSection::getSymbolByIndex(uint32_t Index) {
85325d7b4fbSAlexey Lapshin   Expected<const Symbol *> Sym =
85425d7b4fbSAlexey Lapshin       static_cast<const SymbolTableSection *>(this)->getSymbolByIndex(Index);
85525d7b4fbSAlexey Lapshin   if (!Sym)
85625d7b4fbSAlexey Lapshin     return Sym.takeError();
85725d7b4fbSAlexey Lapshin 
85825d7b4fbSAlexey Lapshin   return const_cast<Symbol *>(*Sym);
85925d7b4fbSAlexey Lapshin }
86025d7b4fbSAlexey Lapshin 
86125d7b4fbSAlexey Lapshin template <class ELFT>
86225d7b4fbSAlexey Lapshin Error ELFSectionWriter<ELFT>::visit(const SymbolTableSection &Sec) {
86325d7b4fbSAlexey Lapshin   Elf_Sym *Sym = reinterpret_cast<Elf_Sym *>(Out.getBufferStart() + Sec.Offset);
86425d7b4fbSAlexey Lapshin   // Loop though symbols setting each entry of the symbol table.
86525d7b4fbSAlexey Lapshin   for (const std::unique_ptr<Symbol> &Symbol : Sec.Symbols) {
86625d7b4fbSAlexey Lapshin     Sym->st_name = Symbol->NameIndex;
86725d7b4fbSAlexey Lapshin     Sym->st_value = Symbol->Value;
86825d7b4fbSAlexey Lapshin     Sym->st_size = Symbol->Size;
86925d7b4fbSAlexey Lapshin     Sym->st_other = Symbol->Visibility;
87025d7b4fbSAlexey Lapshin     Sym->setBinding(Symbol->Binding);
87125d7b4fbSAlexey Lapshin     Sym->setType(Symbol->Type);
87225d7b4fbSAlexey Lapshin     Sym->st_shndx = Symbol->getShndx();
87325d7b4fbSAlexey Lapshin     ++Sym;
87425d7b4fbSAlexey Lapshin   }
87525d7b4fbSAlexey Lapshin   return Error::success();
87625d7b4fbSAlexey Lapshin }
87725d7b4fbSAlexey Lapshin 
87825d7b4fbSAlexey Lapshin Error SymbolTableSection::accept(SectionVisitor &Visitor) const {
87925d7b4fbSAlexey Lapshin   return Visitor.visit(*this);
88025d7b4fbSAlexey Lapshin }
88125d7b4fbSAlexey Lapshin 
88225d7b4fbSAlexey Lapshin Error SymbolTableSection::accept(MutableSectionVisitor &Visitor) {
88325d7b4fbSAlexey Lapshin   return Visitor.visit(*this);
88425d7b4fbSAlexey Lapshin }
88525d7b4fbSAlexey Lapshin 
88625d7b4fbSAlexey Lapshin StringRef RelocationSectionBase::getNamePrefix() const {
88725d7b4fbSAlexey Lapshin   switch (Type) {
88825d7b4fbSAlexey Lapshin   case SHT_REL:
88925d7b4fbSAlexey Lapshin     return ".rel";
89025d7b4fbSAlexey Lapshin   case SHT_RELA:
89125d7b4fbSAlexey Lapshin     return ".rela";
8929bb4cd59SFangrui Song   case SHT_CREL:
8939bb4cd59SFangrui Song     return ".crel";
89425d7b4fbSAlexey Lapshin   default:
89525d7b4fbSAlexey Lapshin     llvm_unreachable("not a relocation section");
89625d7b4fbSAlexey Lapshin   }
89725d7b4fbSAlexey Lapshin }
89825d7b4fbSAlexey Lapshin 
89925d7b4fbSAlexey Lapshin Error RelocationSection::removeSectionReferences(
90025d7b4fbSAlexey Lapshin     bool AllowBrokenLinks, function_ref<bool(const SectionBase *)> ToRemove) {
90125d7b4fbSAlexey Lapshin   if (ToRemove(Symbols)) {
90225d7b4fbSAlexey Lapshin     if (!AllowBrokenLinks)
90325d7b4fbSAlexey Lapshin       return createStringError(
90425d7b4fbSAlexey Lapshin           llvm::errc::invalid_argument,
90525d7b4fbSAlexey Lapshin           "symbol table '%s' cannot be removed because it is "
90625d7b4fbSAlexey Lapshin           "referenced by the relocation section '%s'",
90725d7b4fbSAlexey Lapshin           Symbols->Name.data(), this->Name.data());
90825d7b4fbSAlexey Lapshin     Symbols = nullptr;
90925d7b4fbSAlexey Lapshin   }
91025d7b4fbSAlexey Lapshin 
91125d7b4fbSAlexey Lapshin   for (const Relocation &R : Relocations) {
91225d7b4fbSAlexey Lapshin     if (!R.RelocSymbol || !R.RelocSymbol->DefinedIn ||
91325d7b4fbSAlexey Lapshin         !ToRemove(R.RelocSymbol->DefinedIn))
91425d7b4fbSAlexey Lapshin       continue;
91525d7b4fbSAlexey Lapshin     return createStringError(llvm::errc::invalid_argument,
91625d7b4fbSAlexey Lapshin                              "section '%s' cannot be removed: (%s+0x%" PRIx64
91725d7b4fbSAlexey Lapshin                              ") has relocation against symbol '%s'",
91825d7b4fbSAlexey Lapshin                              R.RelocSymbol->DefinedIn->Name.data(),
91925d7b4fbSAlexey Lapshin                              SecToApplyRel->Name.data(), R.Offset,
92025d7b4fbSAlexey Lapshin                              R.RelocSymbol->Name.c_str());
92125d7b4fbSAlexey Lapshin   }
92225d7b4fbSAlexey Lapshin 
92325d7b4fbSAlexey Lapshin   return Error::success();
92425d7b4fbSAlexey Lapshin }
92525d7b4fbSAlexey Lapshin 
92625d7b4fbSAlexey Lapshin template <class SymTabType>
92725d7b4fbSAlexey Lapshin Error RelocSectionWithSymtabBase<SymTabType>::initialize(
92825d7b4fbSAlexey Lapshin     SectionTableRef SecTable) {
92925d7b4fbSAlexey Lapshin   if (Link != SHN_UNDEF) {
93025d7b4fbSAlexey Lapshin     Expected<SymTabType *> Sec = SecTable.getSectionOfType<SymTabType>(
93125d7b4fbSAlexey Lapshin         Link,
93225d7b4fbSAlexey Lapshin         "Link field value " + Twine(Link) + " in section " + Name +
93325d7b4fbSAlexey Lapshin             " is invalid",
93425d7b4fbSAlexey Lapshin         "Link field value " + Twine(Link) + " in section " + Name +
93525d7b4fbSAlexey Lapshin             " is not a symbol table");
93625d7b4fbSAlexey Lapshin     if (!Sec)
93725d7b4fbSAlexey Lapshin       return Sec.takeError();
93825d7b4fbSAlexey Lapshin 
93925d7b4fbSAlexey Lapshin     setSymTab(*Sec);
94025d7b4fbSAlexey Lapshin   }
94125d7b4fbSAlexey Lapshin 
94225d7b4fbSAlexey Lapshin   if (Info != SHN_UNDEF) {
94325d7b4fbSAlexey Lapshin     Expected<SectionBase *> Sec =
94425d7b4fbSAlexey Lapshin         SecTable.getSection(Info, "Info field value " + Twine(Info) +
94525d7b4fbSAlexey Lapshin                                       " in section " + Name + " is invalid");
94625d7b4fbSAlexey Lapshin     if (!Sec)
94725d7b4fbSAlexey Lapshin       return Sec.takeError();
94825d7b4fbSAlexey Lapshin 
94925d7b4fbSAlexey Lapshin     setSection(*Sec);
95025d7b4fbSAlexey Lapshin   } else
95125d7b4fbSAlexey Lapshin     setSection(nullptr);
95225d7b4fbSAlexey Lapshin 
95325d7b4fbSAlexey Lapshin   return Error::success();
95425d7b4fbSAlexey Lapshin }
95525d7b4fbSAlexey Lapshin 
95625d7b4fbSAlexey Lapshin template <class SymTabType>
95725d7b4fbSAlexey Lapshin void RelocSectionWithSymtabBase<SymTabType>::finalize() {
95825d7b4fbSAlexey Lapshin   this->Link = Symbols ? Symbols->Index : 0;
95925d7b4fbSAlexey Lapshin 
96025d7b4fbSAlexey Lapshin   if (SecToApplyRel != nullptr)
96125d7b4fbSAlexey Lapshin     this->Info = SecToApplyRel->Index;
96225d7b4fbSAlexey Lapshin }
96325d7b4fbSAlexey Lapshin 
96425d7b4fbSAlexey Lapshin template <class ELFT>
96525d7b4fbSAlexey Lapshin static void setAddend(Elf_Rel_Impl<ELFT, false> &, uint64_t) {}
96625d7b4fbSAlexey Lapshin 
96725d7b4fbSAlexey Lapshin template <class ELFT>
96825d7b4fbSAlexey Lapshin static void setAddend(Elf_Rel_Impl<ELFT, true> &Rela, uint64_t Addend) {
96925d7b4fbSAlexey Lapshin   Rela.r_addend = Addend;
97025d7b4fbSAlexey Lapshin }
97125d7b4fbSAlexey Lapshin 
97225d7b4fbSAlexey Lapshin template <class RelRange, class T>
97325d7b4fbSAlexey Lapshin static void writeRel(const RelRange &Relocations, T *Buf, bool IsMips64EL) {
97425d7b4fbSAlexey Lapshin   for (const auto &Reloc : Relocations) {
97525d7b4fbSAlexey Lapshin     Buf->r_offset = Reloc.Offset;
97625d7b4fbSAlexey Lapshin     setAddend(*Buf, Reloc.Addend);
97725d7b4fbSAlexey Lapshin     Buf->setSymbolAndType(Reloc.RelocSymbol ? Reloc.RelocSymbol->Index : 0,
97825d7b4fbSAlexey Lapshin                           Reloc.Type, IsMips64EL);
97925d7b4fbSAlexey Lapshin     ++Buf;
98025d7b4fbSAlexey Lapshin   }
98125d7b4fbSAlexey Lapshin }
98225d7b4fbSAlexey Lapshin 
98325d7b4fbSAlexey Lapshin template <class ELFT>
98425d7b4fbSAlexey Lapshin Error ELFSectionWriter<ELFT>::visit(const RelocationSection &Sec) {
98525d7b4fbSAlexey Lapshin   uint8_t *Buf = reinterpret_cast<uint8_t *>(Out.getBufferStart()) + Sec.Offset;
9869bb4cd59SFangrui Song   if (Sec.Type == SHT_CREL) {
9879bb4cd59SFangrui Song     auto Content = encodeCrel<ELFT::Is64Bits>(Sec.Relocations);
9889bb4cd59SFangrui Song     memcpy(Buf, Content.data(), Content.size());
9899bb4cd59SFangrui Song   } else if (Sec.Type == SHT_REL) {
99025d7b4fbSAlexey Lapshin     writeRel(Sec.Relocations, reinterpret_cast<Elf_Rel *>(Buf),
99125d7b4fbSAlexey Lapshin              Sec.getObject().IsMips64EL);
9929bb4cd59SFangrui Song   } else {
99325d7b4fbSAlexey Lapshin     writeRel(Sec.Relocations, reinterpret_cast<Elf_Rela *>(Buf),
99425d7b4fbSAlexey Lapshin              Sec.getObject().IsMips64EL);
9959bb4cd59SFangrui Song   }
99625d7b4fbSAlexey Lapshin   return Error::success();
99725d7b4fbSAlexey Lapshin }
99825d7b4fbSAlexey Lapshin 
99925d7b4fbSAlexey Lapshin Error RelocationSection::accept(SectionVisitor &Visitor) const {
100025d7b4fbSAlexey Lapshin   return Visitor.visit(*this);
100125d7b4fbSAlexey Lapshin }
100225d7b4fbSAlexey Lapshin 
100325d7b4fbSAlexey Lapshin Error RelocationSection::accept(MutableSectionVisitor &Visitor) {
100425d7b4fbSAlexey Lapshin   return Visitor.visit(*this);
100525d7b4fbSAlexey Lapshin }
100625d7b4fbSAlexey Lapshin 
100725d7b4fbSAlexey Lapshin Error RelocationSection::removeSymbols(
100825d7b4fbSAlexey Lapshin     function_ref<bool(const Symbol &)> ToRemove) {
100925d7b4fbSAlexey Lapshin   for (const Relocation &Reloc : Relocations)
101025d7b4fbSAlexey Lapshin     if (Reloc.RelocSymbol && ToRemove(*Reloc.RelocSymbol))
101125d7b4fbSAlexey Lapshin       return createStringError(
101225d7b4fbSAlexey Lapshin           llvm::errc::invalid_argument,
101325d7b4fbSAlexey Lapshin           "not stripping symbol '%s' because it is named in a relocation",
101425d7b4fbSAlexey Lapshin           Reloc.RelocSymbol->Name.data());
101525d7b4fbSAlexey Lapshin   return Error::success();
101625d7b4fbSAlexey Lapshin }
101725d7b4fbSAlexey Lapshin 
101825d7b4fbSAlexey Lapshin void RelocationSection::markSymbols() {
101925d7b4fbSAlexey Lapshin   for (const Relocation &Reloc : Relocations)
102025d7b4fbSAlexey Lapshin     if (Reloc.RelocSymbol)
102125d7b4fbSAlexey Lapshin       Reloc.RelocSymbol->Referenced = true;
102225d7b4fbSAlexey Lapshin }
102325d7b4fbSAlexey Lapshin 
102425d7b4fbSAlexey Lapshin void RelocationSection::replaceSectionReferences(
102525d7b4fbSAlexey Lapshin     const DenseMap<SectionBase *, SectionBase *> &FromTo) {
102625d7b4fbSAlexey Lapshin   // Update the target section if it was replaced.
102725d7b4fbSAlexey Lapshin   if (SectionBase *To = FromTo.lookup(SecToApplyRel))
102825d7b4fbSAlexey Lapshin     SecToApplyRel = To;
102925d7b4fbSAlexey Lapshin }
103025d7b4fbSAlexey Lapshin 
103125d7b4fbSAlexey Lapshin Error SectionWriter::visit(const DynamicRelocationSection &Sec) {
103225d7b4fbSAlexey Lapshin   llvm::copy(Sec.Contents, Out.getBufferStart() + Sec.Offset);
103325d7b4fbSAlexey Lapshin   return Error::success();
103425d7b4fbSAlexey Lapshin }
103525d7b4fbSAlexey Lapshin 
103625d7b4fbSAlexey Lapshin Error DynamicRelocationSection::accept(SectionVisitor &Visitor) const {
103725d7b4fbSAlexey Lapshin   return Visitor.visit(*this);
103825d7b4fbSAlexey Lapshin }
103925d7b4fbSAlexey Lapshin 
104025d7b4fbSAlexey Lapshin Error DynamicRelocationSection::accept(MutableSectionVisitor &Visitor) {
104125d7b4fbSAlexey Lapshin   return Visitor.visit(*this);
104225d7b4fbSAlexey Lapshin }
104325d7b4fbSAlexey Lapshin 
104425d7b4fbSAlexey Lapshin Error DynamicRelocationSection::removeSectionReferences(
104525d7b4fbSAlexey Lapshin     bool AllowBrokenLinks, function_ref<bool(const SectionBase *)> ToRemove) {
104625d7b4fbSAlexey Lapshin   if (ToRemove(Symbols)) {
104725d7b4fbSAlexey Lapshin     if (!AllowBrokenLinks)
104825d7b4fbSAlexey Lapshin       return createStringError(
104925d7b4fbSAlexey Lapshin           llvm::errc::invalid_argument,
105025d7b4fbSAlexey Lapshin           "symbol table '%s' cannot be removed because it is "
105125d7b4fbSAlexey Lapshin           "referenced by the relocation section '%s'",
105225d7b4fbSAlexey Lapshin           Symbols->Name.data(), this->Name.data());
105325d7b4fbSAlexey Lapshin     Symbols = nullptr;
105425d7b4fbSAlexey Lapshin   }
105525d7b4fbSAlexey Lapshin 
105625d7b4fbSAlexey Lapshin   // SecToApplyRel contains a section referenced by sh_info field. It keeps
105725d7b4fbSAlexey Lapshin   // a section to which the relocation section applies. When we remove any
105825d7b4fbSAlexey Lapshin   // sections we also remove their relocation sections. Since we do that much
105925d7b4fbSAlexey Lapshin   // earlier, this assert should never be triggered.
106025d7b4fbSAlexey Lapshin   assert(!SecToApplyRel || !ToRemove(SecToApplyRel));
106125d7b4fbSAlexey Lapshin   return Error::success();
106225d7b4fbSAlexey Lapshin }
106325d7b4fbSAlexey Lapshin 
106425d7b4fbSAlexey Lapshin Error Section::removeSectionReferences(
106525d7b4fbSAlexey Lapshin     bool AllowBrokenDependency,
106625d7b4fbSAlexey Lapshin     function_ref<bool(const SectionBase *)> ToRemove) {
106725d7b4fbSAlexey Lapshin   if (ToRemove(LinkSection)) {
106825d7b4fbSAlexey Lapshin     if (!AllowBrokenDependency)
106925d7b4fbSAlexey Lapshin       return createStringError(llvm::errc::invalid_argument,
107025d7b4fbSAlexey Lapshin                                "section '%s' cannot be removed because it is "
107125d7b4fbSAlexey Lapshin                                "referenced by the section '%s'",
107225d7b4fbSAlexey Lapshin                                LinkSection->Name.data(), this->Name.data());
107325d7b4fbSAlexey Lapshin     LinkSection = nullptr;
107425d7b4fbSAlexey Lapshin   }
107525d7b4fbSAlexey Lapshin   return Error::success();
107625d7b4fbSAlexey Lapshin }
107725d7b4fbSAlexey Lapshin 
107825d7b4fbSAlexey Lapshin void GroupSection::finalize() {
107925d7b4fbSAlexey Lapshin   this->Info = Sym ? Sym->Index : 0;
108025d7b4fbSAlexey Lapshin   this->Link = SymTab ? SymTab->Index : 0;
108125d7b4fbSAlexey Lapshin   // Linker deduplication for GRP_COMDAT is based on Sym->Name. The local/global
108225d7b4fbSAlexey Lapshin   // status is not part of the equation. If Sym is localized, the intention is
108325d7b4fbSAlexey Lapshin   // likely to make the group fully localized. Drop GRP_COMDAT to suppress
108425d7b4fbSAlexey Lapshin   // deduplication. See https://groups.google.com/g/generic-abi/c/2X6mR-s2zoc
108525d7b4fbSAlexey Lapshin   if ((FlagWord & GRP_COMDAT) && Sym && Sym->Binding == STB_LOCAL)
108625d7b4fbSAlexey Lapshin     this->FlagWord &= ~GRP_COMDAT;
108725d7b4fbSAlexey Lapshin }
108825d7b4fbSAlexey Lapshin 
108925d7b4fbSAlexey Lapshin Error GroupSection::removeSectionReferences(
109025d7b4fbSAlexey Lapshin     bool AllowBrokenLinks, function_ref<bool(const SectionBase *)> ToRemove) {
109125d7b4fbSAlexey Lapshin   if (ToRemove(SymTab)) {
109225d7b4fbSAlexey Lapshin     if (!AllowBrokenLinks)
109325d7b4fbSAlexey Lapshin       return createStringError(
109425d7b4fbSAlexey Lapshin           llvm::errc::invalid_argument,
109525d7b4fbSAlexey Lapshin           "section '.symtab' cannot be removed because it is "
109625d7b4fbSAlexey Lapshin           "referenced by the group section '%s'",
109725d7b4fbSAlexey Lapshin           this->Name.data());
109825d7b4fbSAlexey Lapshin     SymTab = nullptr;
109925d7b4fbSAlexey Lapshin     Sym = nullptr;
110025d7b4fbSAlexey Lapshin   }
110125d7b4fbSAlexey Lapshin   llvm::erase_if(GroupMembers, ToRemove);
110225d7b4fbSAlexey Lapshin   return Error::success();
110325d7b4fbSAlexey Lapshin }
110425d7b4fbSAlexey Lapshin 
110525d7b4fbSAlexey Lapshin Error GroupSection::removeSymbols(function_ref<bool(const Symbol &)> ToRemove) {
110625d7b4fbSAlexey Lapshin   if (ToRemove(*Sym))
110725d7b4fbSAlexey Lapshin     return createStringError(llvm::errc::invalid_argument,
110825d7b4fbSAlexey Lapshin                              "symbol '%s' cannot be removed because it is "
110925d7b4fbSAlexey Lapshin                              "referenced by the section '%s[%d]'",
111025d7b4fbSAlexey Lapshin                              Sym->Name.data(), this->Name.data(), this->Index);
111125d7b4fbSAlexey Lapshin   return Error::success();
111225d7b4fbSAlexey Lapshin }
111325d7b4fbSAlexey Lapshin 
111425d7b4fbSAlexey Lapshin void GroupSection::markSymbols() {
111525d7b4fbSAlexey Lapshin   if (Sym)
111625d7b4fbSAlexey Lapshin     Sym->Referenced = true;
111725d7b4fbSAlexey Lapshin }
111825d7b4fbSAlexey Lapshin 
111925d7b4fbSAlexey Lapshin void GroupSection::replaceSectionReferences(
112025d7b4fbSAlexey Lapshin     const DenseMap<SectionBase *, SectionBase *> &FromTo) {
112125d7b4fbSAlexey Lapshin   for (SectionBase *&Sec : GroupMembers)
112225d7b4fbSAlexey Lapshin     if (SectionBase *To = FromTo.lookup(Sec))
112325d7b4fbSAlexey Lapshin       Sec = To;
112425d7b4fbSAlexey Lapshin }
112525d7b4fbSAlexey Lapshin 
112625d7b4fbSAlexey Lapshin void GroupSection::onRemove() {
112725d7b4fbSAlexey Lapshin   // As the header section of the group is removed, drop the Group flag in its
112825d7b4fbSAlexey Lapshin   // former members.
112925d7b4fbSAlexey Lapshin   for (SectionBase *Sec : GroupMembers)
113025d7b4fbSAlexey Lapshin     Sec->Flags &= ~SHF_GROUP;
113125d7b4fbSAlexey Lapshin }
113225d7b4fbSAlexey Lapshin 
113325d7b4fbSAlexey Lapshin Error Section::initialize(SectionTableRef SecTable) {
113425d7b4fbSAlexey Lapshin   if (Link == ELF::SHN_UNDEF)
113525d7b4fbSAlexey Lapshin     return Error::success();
113625d7b4fbSAlexey Lapshin 
113725d7b4fbSAlexey Lapshin   Expected<SectionBase *> Sec =
113825d7b4fbSAlexey Lapshin       SecTable.getSection(Link, "Link field value " + Twine(Link) +
113925d7b4fbSAlexey Lapshin                                     " in section " + Name + " is invalid");
114025d7b4fbSAlexey Lapshin   if (!Sec)
114125d7b4fbSAlexey Lapshin     return Sec.takeError();
114225d7b4fbSAlexey Lapshin 
114325d7b4fbSAlexey Lapshin   LinkSection = *Sec;
114425d7b4fbSAlexey Lapshin 
1145744e589cSAndrew Ng   if (LinkSection->Type == ELF::SHT_SYMTAB) {
1146744e589cSAndrew Ng     HasSymTabLink = true;
114725d7b4fbSAlexey Lapshin     LinkSection = nullptr;
1148744e589cSAndrew Ng   }
114925d7b4fbSAlexey Lapshin 
115025d7b4fbSAlexey Lapshin   return Error::success();
115125d7b4fbSAlexey Lapshin }
115225d7b4fbSAlexey Lapshin 
115325d7b4fbSAlexey Lapshin void Section::finalize() { this->Link = LinkSection ? LinkSection->Index : 0; }
115425d7b4fbSAlexey Lapshin 
115525d7b4fbSAlexey Lapshin void GnuDebugLinkSection::init(StringRef File) {
115625d7b4fbSAlexey Lapshin   FileName = sys::path::filename(File);
115725d7b4fbSAlexey Lapshin   // The format for the .gnu_debuglink starts with the file name and is
115825d7b4fbSAlexey Lapshin   // followed by a null terminator and then the CRC32 of the file. The CRC32
115925d7b4fbSAlexey Lapshin   // should be 4 byte aligned. So we add the FileName size, a 1 for the null
116025d7b4fbSAlexey Lapshin   // byte, and then finally push the size to alignment and add 4.
116125d7b4fbSAlexey Lapshin   Size = alignTo(FileName.size() + 1, 4) + 4;
116225d7b4fbSAlexey Lapshin   // The CRC32 will only be aligned if we align the whole section.
116325d7b4fbSAlexey Lapshin   Align = 4;
116425d7b4fbSAlexey Lapshin   Type = OriginalType = ELF::SHT_PROGBITS;
116525d7b4fbSAlexey Lapshin   Name = ".gnu_debuglink";
116625d7b4fbSAlexey Lapshin   // For sections not found in segments, OriginalOffset is only used to
116725d7b4fbSAlexey Lapshin   // establish the order that sections should go in. By using the maximum
116825d7b4fbSAlexey Lapshin   // possible offset we cause this section to wind up at the end.
116925d7b4fbSAlexey Lapshin   OriginalOffset = std::numeric_limits<uint64_t>::max();
117025d7b4fbSAlexey Lapshin }
117125d7b4fbSAlexey Lapshin 
117225d7b4fbSAlexey Lapshin GnuDebugLinkSection::GnuDebugLinkSection(StringRef File,
117325d7b4fbSAlexey Lapshin                                          uint32_t PrecomputedCRC)
117425d7b4fbSAlexey Lapshin     : FileName(File), CRC32(PrecomputedCRC) {
117525d7b4fbSAlexey Lapshin   init(File);
117625d7b4fbSAlexey Lapshin }
117725d7b4fbSAlexey Lapshin 
117825d7b4fbSAlexey Lapshin template <class ELFT>
117925d7b4fbSAlexey Lapshin Error ELFSectionWriter<ELFT>::visit(const GnuDebugLinkSection &Sec) {
118025d7b4fbSAlexey Lapshin   unsigned char *Buf =
118125d7b4fbSAlexey Lapshin       reinterpret_cast<uint8_t *>(Out.getBufferStart()) + Sec.Offset;
118225d7b4fbSAlexey Lapshin   Elf_Word *CRC =
118325d7b4fbSAlexey Lapshin       reinterpret_cast<Elf_Word *>(Buf + Sec.Size - sizeof(Elf_Word));
118425d7b4fbSAlexey Lapshin   *CRC = Sec.CRC32;
118525d7b4fbSAlexey Lapshin   llvm::copy(Sec.FileName, Buf);
118625d7b4fbSAlexey Lapshin   return Error::success();
118725d7b4fbSAlexey Lapshin }
118825d7b4fbSAlexey Lapshin 
118925d7b4fbSAlexey Lapshin Error GnuDebugLinkSection::accept(SectionVisitor &Visitor) const {
119025d7b4fbSAlexey Lapshin   return Visitor.visit(*this);
119125d7b4fbSAlexey Lapshin }
119225d7b4fbSAlexey Lapshin 
119325d7b4fbSAlexey Lapshin Error GnuDebugLinkSection::accept(MutableSectionVisitor &Visitor) {
119425d7b4fbSAlexey Lapshin   return Visitor.visit(*this);
119525d7b4fbSAlexey Lapshin }
119625d7b4fbSAlexey Lapshin 
119725d7b4fbSAlexey Lapshin template <class ELFT>
119825d7b4fbSAlexey Lapshin Error ELFSectionWriter<ELFT>::visit(const GroupSection &Sec) {
119925d7b4fbSAlexey Lapshin   ELF::Elf32_Word *Buf =
120025d7b4fbSAlexey Lapshin       reinterpret_cast<ELF::Elf32_Word *>(Out.getBufferStart() + Sec.Offset);
120127633538SFangrui Song   endian::write32<ELFT::Endianness>(Buf++, Sec.FlagWord);
120225d7b4fbSAlexey Lapshin   for (SectionBase *S : Sec.GroupMembers)
120327633538SFangrui Song     endian::write32<ELFT::Endianness>(Buf++, S->Index);
120425d7b4fbSAlexey Lapshin   return Error::success();
120525d7b4fbSAlexey Lapshin }
120625d7b4fbSAlexey Lapshin 
120725d7b4fbSAlexey Lapshin Error GroupSection::accept(SectionVisitor &Visitor) const {
120825d7b4fbSAlexey Lapshin   return Visitor.visit(*this);
120925d7b4fbSAlexey Lapshin }
121025d7b4fbSAlexey Lapshin 
121125d7b4fbSAlexey Lapshin Error GroupSection::accept(MutableSectionVisitor &Visitor) {
121225d7b4fbSAlexey Lapshin   return Visitor.visit(*this);
121325d7b4fbSAlexey Lapshin }
121425d7b4fbSAlexey Lapshin 
121525d7b4fbSAlexey Lapshin // Returns true IFF a section is wholly inside the range of a segment
121625d7b4fbSAlexey Lapshin static bool sectionWithinSegment(const SectionBase &Sec, const Segment &Seg) {
121725d7b4fbSAlexey Lapshin   // If a section is empty it should be treated like it has a size of 1. This is
121825d7b4fbSAlexey Lapshin   // to clarify the case when an empty section lies on a boundary between two
121925d7b4fbSAlexey Lapshin   // segments and ensures that the section "belongs" to the second segment and
122025d7b4fbSAlexey Lapshin   // not the first.
122125d7b4fbSAlexey Lapshin   uint64_t SecSize = Sec.Size ? Sec.Size : 1;
122225d7b4fbSAlexey Lapshin 
122325d7b4fbSAlexey Lapshin   // Ignore just added sections.
122425d7b4fbSAlexey Lapshin   if (Sec.OriginalOffset == std::numeric_limits<uint64_t>::max())
122525d7b4fbSAlexey Lapshin     return false;
122625d7b4fbSAlexey Lapshin 
122725d7b4fbSAlexey Lapshin   if (Sec.Type == SHT_NOBITS) {
122825d7b4fbSAlexey Lapshin     if (!(Sec.Flags & SHF_ALLOC))
122925d7b4fbSAlexey Lapshin       return false;
123025d7b4fbSAlexey Lapshin 
123125d7b4fbSAlexey Lapshin     bool SectionIsTLS = Sec.Flags & SHF_TLS;
123225d7b4fbSAlexey Lapshin     bool SegmentIsTLS = Seg.Type == PT_TLS;
123325d7b4fbSAlexey Lapshin     if (SectionIsTLS != SegmentIsTLS)
123425d7b4fbSAlexey Lapshin       return false;
123525d7b4fbSAlexey Lapshin 
123625d7b4fbSAlexey Lapshin     return Seg.VAddr <= Sec.Addr &&
123725d7b4fbSAlexey Lapshin            Seg.VAddr + Seg.MemSize >= Sec.Addr + SecSize;
123825d7b4fbSAlexey Lapshin   }
123925d7b4fbSAlexey Lapshin 
124025d7b4fbSAlexey Lapshin   return Seg.Offset <= Sec.OriginalOffset &&
124125d7b4fbSAlexey Lapshin          Seg.Offset + Seg.FileSize >= Sec.OriginalOffset + SecSize;
124225d7b4fbSAlexey Lapshin }
124325d7b4fbSAlexey Lapshin 
124425d7b4fbSAlexey Lapshin // Returns true IFF a segment's original offset is inside of another segment's
124525d7b4fbSAlexey Lapshin // range.
124625d7b4fbSAlexey Lapshin static bool segmentOverlapsSegment(const Segment &Child,
124725d7b4fbSAlexey Lapshin                                    const Segment &Parent) {
124825d7b4fbSAlexey Lapshin 
124925d7b4fbSAlexey Lapshin   return Parent.OriginalOffset <= Child.OriginalOffset &&
125025d7b4fbSAlexey Lapshin          Parent.OriginalOffset + Parent.FileSize > Child.OriginalOffset;
125125d7b4fbSAlexey Lapshin }
125225d7b4fbSAlexey Lapshin 
125325d7b4fbSAlexey Lapshin static bool compareSegmentsByOffset(const Segment *A, const Segment *B) {
125425d7b4fbSAlexey Lapshin   // Any segment without a parent segment should come before a segment
125525d7b4fbSAlexey Lapshin   // that has a parent segment.
125625d7b4fbSAlexey Lapshin   if (A->OriginalOffset < B->OriginalOffset)
125725d7b4fbSAlexey Lapshin     return true;
125825d7b4fbSAlexey Lapshin   if (A->OriginalOffset > B->OriginalOffset)
125925d7b4fbSAlexey Lapshin     return false;
1260ef283790SFangrui Song   // If alignments are different, the one with a smaller alignment cannot be the
1261ef283790SFangrui Song   // parent; otherwise, layoutSegments will not respect the larger alignment
1262ef283790SFangrui Song   // requirement. This rule ensures that PT_LOAD/PT_INTERP/PT_GNU_RELRO/PT_TLS
1263ef283790SFangrui Song   // segments at the same offset will be aligned correctly.
1264ef283790SFangrui Song   if (A->Align != B->Align)
1265ef283790SFangrui Song     return A->Align > B->Align;
126625d7b4fbSAlexey Lapshin   return A->Index < B->Index;
126725d7b4fbSAlexey Lapshin }
126825d7b4fbSAlexey Lapshin 
126925d7b4fbSAlexey Lapshin void BasicELFBuilder::initFileHeader() {
127025d7b4fbSAlexey Lapshin   Obj->Flags = 0x0;
127125d7b4fbSAlexey Lapshin   Obj->Type = ET_REL;
127225d7b4fbSAlexey Lapshin   Obj->OSABI = ELFOSABI_NONE;
127325d7b4fbSAlexey Lapshin   Obj->ABIVersion = 0;
127425d7b4fbSAlexey Lapshin   Obj->Entry = 0x0;
127525d7b4fbSAlexey Lapshin   Obj->Machine = EM_NONE;
127625d7b4fbSAlexey Lapshin   Obj->Version = 1;
127725d7b4fbSAlexey Lapshin }
127825d7b4fbSAlexey Lapshin 
127925d7b4fbSAlexey Lapshin void BasicELFBuilder::initHeaderSegment() { Obj->ElfHdrSegment.Index = 0; }
128025d7b4fbSAlexey Lapshin 
128125d7b4fbSAlexey Lapshin StringTableSection *BasicELFBuilder::addStrTab() {
128225d7b4fbSAlexey Lapshin   auto &StrTab = Obj->addSection<StringTableSection>();
128325d7b4fbSAlexey Lapshin   StrTab.Name = ".strtab";
128425d7b4fbSAlexey Lapshin 
128525d7b4fbSAlexey Lapshin   Obj->SectionNames = &StrTab;
128625d7b4fbSAlexey Lapshin   return &StrTab;
128725d7b4fbSAlexey Lapshin }
128825d7b4fbSAlexey Lapshin 
128925d7b4fbSAlexey Lapshin SymbolTableSection *BasicELFBuilder::addSymTab(StringTableSection *StrTab) {
129025d7b4fbSAlexey Lapshin   auto &SymTab = Obj->addSection<SymbolTableSection>();
129125d7b4fbSAlexey Lapshin 
129225d7b4fbSAlexey Lapshin   SymTab.Name = ".symtab";
129325d7b4fbSAlexey Lapshin   SymTab.Link = StrTab->Index;
129425d7b4fbSAlexey Lapshin 
129525d7b4fbSAlexey Lapshin   // The symbol table always needs a null symbol
129625d7b4fbSAlexey Lapshin   SymTab.addSymbol("", 0, 0, nullptr, 0, 0, 0, 0);
129725d7b4fbSAlexey Lapshin 
129825d7b4fbSAlexey Lapshin   Obj->SymbolTable = &SymTab;
129925d7b4fbSAlexey Lapshin   return &SymTab;
130025d7b4fbSAlexey Lapshin }
130125d7b4fbSAlexey Lapshin 
130225d7b4fbSAlexey Lapshin Error BasicELFBuilder::initSections() {
130325d7b4fbSAlexey Lapshin   for (SectionBase &Sec : Obj->sections())
130425d7b4fbSAlexey Lapshin     if (Error Err = Sec.initialize(Obj->sections()))
130525d7b4fbSAlexey Lapshin       return Err;
130625d7b4fbSAlexey Lapshin 
130725d7b4fbSAlexey Lapshin   return Error::success();
130825d7b4fbSAlexey Lapshin }
130925d7b4fbSAlexey Lapshin 
131025d7b4fbSAlexey Lapshin void BinaryELFBuilder::addData(SymbolTableSection *SymTab) {
131125d7b4fbSAlexey Lapshin   auto Data = ArrayRef<uint8_t>(
131225d7b4fbSAlexey Lapshin       reinterpret_cast<const uint8_t *>(MemBuf->getBufferStart()),
131325d7b4fbSAlexey Lapshin       MemBuf->getBufferSize());
131425d7b4fbSAlexey Lapshin   auto &DataSection = Obj->addSection<Section>(Data);
131525d7b4fbSAlexey Lapshin   DataSection.Name = ".data";
131625d7b4fbSAlexey Lapshin   DataSection.Type = ELF::SHT_PROGBITS;
131725d7b4fbSAlexey Lapshin   DataSection.Size = Data.size();
131825d7b4fbSAlexey Lapshin   DataSection.Flags = ELF::SHF_ALLOC | ELF::SHF_WRITE;
131925d7b4fbSAlexey Lapshin 
132025d7b4fbSAlexey Lapshin   std::string SanitizedFilename = MemBuf->getBufferIdentifier().str();
132125d7b4fbSAlexey Lapshin   std::replace_if(
132225d7b4fbSAlexey Lapshin       std::begin(SanitizedFilename), std::end(SanitizedFilename),
132325d7b4fbSAlexey Lapshin       [](char C) { return !isAlnum(C); }, '_');
132425d7b4fbSAlexey Lapshin   Twine Prefix = Twine("_binary_") + SanitizedFilename;
132525d7b4fbSAlexey Lapshin 
132625d7b4fbSAlexey Lapshin   SymTab->addSymbol(Prefix + "_start", STB_GLOBAL, STT_NOTYPE, &DataSection,
132725d7b4fbSAlexey Lapshin                     /*Value=*/0, NewSymbolVisibility, 0, 0);
132825d7b4fbSAlexey Lapshin   SymTab->addSymbol(Prefix + "_end", STB_GLOBAL, STT_NOTYPE, &DataSection,
132925d7b4fbSAlexey Lapshin                     /*Value=*/DataSection.Size, NewSymbolVisibility, 0, 0);
133025d7b4fbSAlexey Lapshin   SymTab->addSymbol(Prefix + "_size", STB_GLOBAL, STT_NOTYPE, nullptr,
133125d7b4fbSAlexey Lapshin                     /*Value=*/DataSection.Size, NewSymbolVisibility, SHN_ABS,
133225d7b4fbSAlexey Lapshin                     0);
133325d7b4fbSAlexey Lapshin }
133425d7b4fbSAlexey Lapshin 
133525d7b4fbSAlexey Lapshin Expected<std::unique_ptr<Object>> BinaryELFBuilder::build() {
133625d7b4fbSAlexey Lapshin   initFileHeader();
133725d7b4fbSAlexey Lapshin   initHeaderSegment();
133825d7b4fbSAlexey Lapshin 
133925d7b4fbSAlexey Lapshin   SymbolTableSection *SymTab = addSymTab(addStrTab());
134025d7b4fbSAlexey Lapshin   if (Error Err = initSections())
134125d7b4fbSAlexey Lapshin     return std::move(Err);
134225d7b4fbSAlexey Lapshin   addData(SymTab);
134325d7b4fbSAlexey Lapshin 
134425d7b4fbSAlexey Lapshin   return std::move(Obj);
134525d7b4fbSAlexey Lapshin }
134625d7b4fbSAlexey Lapshin 
134725d7b4fbSAlexey Lapshin // Adds sections from IHEX data file. Data should have been
134825d7b4fbSAlexey Lapshin // fully validated by this time.
134925d7b4fbSAlexey Lapshin void IHexELFBuilder::addDataSections() {
135025d7b4fbSAlexey Lapshin   OwnedDataSection *Section = nullptr;
135125d7b4fbSAlexey Lapshin   uint64_t SegmentAddr = 0, BaseAddr = 0;
135225d7b4fbSAlexey Lapshin   uint32_t SecNo = 1;
135325d7b4fbSAlexey Lapshin 
135425d7b4fbSAlexey Lapshin   for (const IHexRecord &R : Records) {
135525d7b4fbSAlexey Lapshin     uint64_t RecAddr;
135625d7b4fbSAlexey Lapshin     switch (R.Type) {
135725d7b4fbSAlexey Lapshin     case IHexRecord::Data:
135825d7b4fbSAlexey Lapshin       // Ignore empty data records
135925d7b4fbSAlexey Lapshin       if (R.HexData.empty())
136025d7b4fbSAlexey Lapshin         continue;
136125d7b4fbSAlexey Lapshin       RecAddr = R.Addr + SegmentAddr + BaseAddr;
136225d7b4fbSAlexey Lapshin       if (!Section || Section->Addr + Section->Size != RecAddr) {
136325d7b4fbSAlexey Lapshin         // OriginalOffset field is only used to sort sections before layout, so
136425d7b4fbSAlexey Lapshin         // instead of keeping track of real offsets in IHEX file, and as
136525d7b4fbSAlexey Lapshin         // layoutSections() and layoutSectionsForOnlyKeepDebug() use
136625d7b4fbSAlexey Lapshin         // llvm::stable_sort(), we can just set it to a constant (zero).
136725d7b4fbSAlexey Lapshin         Section = &Obj->addSection<OwnedDataSection>(
136825d7b4fbSAlexey Lapshin             ".sec" + std::to_string(SecNo), RecAddr,
136925d7b4fbSAlexey Lapshin             ELF::SHF_ALLOC | ELF::SHF_WRITE, 0);
137025d7b4fbSAlexey Lapshin         SecNo++;
137125d7b4fbSAlexey Lapshin       }
137225d7b4fbSAlexey Lapshin       Section->appendHexData(R.HexData);
137325d7b4fbSAlexey Lapshin       break;
137425d7b4fbSAlexey Lapshin     case IHexRecord::EndOfFile:
137525d7b4fbSAlexey Lapshin       break;
137625d7b4fbSAlexey Lapshin     case IHexRecord::SegmentAddr:
137725d7b4fbSAlexey Lapshin       // 20-bit segment address.
137825d7b4fbSAlexey Lapshin       SegmentAddr = checkedGetHex<uint16_t>(R.HexData) << 4;
137925d7b4fbSAlexey Lapshin       break;
138025d7b4fbSAlexey Lapshin     case IHexRecord::StartAddr80x86:
138125d7b4fbSAlexey Lapshin     case IHexRecord::StartAddr:
138225d7b4fbSAlexey Lapshin       Obj->Entry = checkedGetHex<uint32_t>(R.HexData);
138325d7b4fbSAlexey Lapshin       assert(Obj->Entry <= 0xFFFFFU);
138425d7b4fbSAlexey Lapshin       break;
138525d7b4fbSAlexey Lapshin     case IHexRecord::ExtendedAddr:
138625d7b4fbSAlexey Lapshin       // 16-31 bits of linear base address
138725d7b4fbSAlexey Lapshin       BaseAddr = checkedGetHex<uint16_t>(R.HexData) << 16;
138825d7b4fbSAlexey Lapshin       break;
138925d7b4fbSAlexey Lapshin     default:
139025d7b4fbSAlexey Lapshin       llvm_unreachable("unknown record type");
139125d7b4fbSAlexey Lapshin     }
139225d7b4fbSAlexey Lapshin   }
139325d7b4fbSAlexey Lapshin }
139425d7b4fbSAlexey Lapshin 
139525d7b4fbSAlexey Lapshin Expected<std::unique_ptr<Object>> IHexELFBuilder::build() {
139625d7b4fbSAlexey Lapshin   initFileHeader();
139725d7b4fbSAlexey Lapshin   initHeaderSegment();
139825d7b4fbSAlexey Lapshin   StringTableSection *StrTab = addStrTab();
139925d7b4fbSAlexey Lapshin   addSymTab(StrTab);
140025d7b4fbSAlexey Lapshin   if (Error Err = initSections())
140125d7b4fbSAlexey Lapshin     return std::move(Err);
140225d7b4fbSAlexey Lapshin   addDataSections();
140325d7b4fbSAlexey Lapshin 
140425d7b4fbSAlexey Lapshin   return std::move(Obj);
140525d7b4fbSAlexey Lapshin }
140625d7b4fbSAlexey Lapshin 
140725d7b4fbSAlexey Lapshin template <class ELFT>
140825d7b4fbSAlexey Lapshin ELFBuilder<ELFT>::ELFBuilder(const ELFObjectFile<ELFT> &ElfObj, Object &Obj,
1409ec941432SFangrui Song                              std::optional<StringRef> ExtractPartition)
141025d7b4fbSAlexey Lapshin     : ElfFile(ElfObj.getELFFile()), Obj(Obj),
141125d7b4fbSAlexey Lapshin       ExtractPartition(ExtractPartition) {
141225d7b4fbSAlexey Lapshin   Obj.IsMips64EL = ElfFile.isMips64EL();
141325d7b4fbSAlexey Lapshin }
141425d7b4fbSAlexey Lapshin 
141525d7b4fbSAlexey Lapshin template <class ELFT> void ELFBuilder<ELFT>::setParentSegment(Segment &Child) {
141625d7b4fbSAlexey Lapshin   for (Segment &Parent : Obj.segments()) {
141725d7b4fbSAlexey Lapshin     // Every segment will overlap with itself but we don't want a segment to
141825d7b4fbSAlexey Lapshin     // be its own parent so we avoid that situation.
141925d7b4fbSAlexey Lapshin     if (&Child != &Parent && segmentOverlapsSegment(Child, Parent)) {
142025d7b4fbSAlexey Lapshin       // We want a canonical "most parental" segment but this requires
142125d7b4fbSAlexey Lapshin       // inspecting the ParentSegment.
142225d7b4fbSAlexey Lapshin       if (compareSegmentsByOffset(&Parent, &Child))
142325d7b4fbSAlexey Lapshin         if (Child.ParentSegment == nullptr ||
142425d7b4fbSAlexey Lapshin             compareSegmentsByOffset(&Parent, Child.ParentSegment)) {
142525d7b4fbSAlexey Lapshin           Child.ParentSegment = &Parent;
142625d7b4fbSAlexey Lapshin         }
142725d7b4fbSAlexey Lapshin     }
142825d7b4fbSAlexey Lapshin   }
142925d7b4fbSAlexey Lapshin }
143025d7b4fbSAlexey Lapshin 
143125d7b4fbSAlexey Lapshin template <class ELFT> Error ELFBuilder<ELFT>::findEhdrOffset() {
143225d7b4fbSAlexey Lapshin   if (!ExtractPartition)
143325d7b4fbSAlexey Lapshin     return Error::success();
143425d7b4fbSAlexey Lapshin 
143525d7b4fbSAlexey Lapshin   for (const SectionBase &Sec : Obj.sections()) {
143625d7b4fbSAlexey Lapshin     if (Sec.Type == SHT_LLVM_PART_EHDR && Sec.Name == *ExtractPartition) {
143725d7b4fbSAlexey Lapshin       EhdrOffset = Sec.Offset;
143825d7b4fbSAlexey Lapshin       return Error::success();
143925d7b4fbSAlexey Lapshin     }
144025d7b4fbSAlexey Lapshin   }
144125d7b4fbSAlexey Lapshin   return createStringError(errc::invalid_argument,
144225d7b4fbSAlexey Lapshin                            "could not find partition named '" +
144325d7b4fbSAlexey Lapshin                                *ExtractPartition + "'");
144425d7b4fbSAlexey Lapshin }
144525d7b4fbSAlexey Lapshin 
144625d7b4fbSAlexey Lapshin template <class ELFT>
144725d7b4fbSAlexey Lapshin Error ELFBuilder<ELFT>::readProgramHeaders(const ELFFile<ELFT> &HeadersFile) {
144825d7b4fbSAlexey Lapshin   uint32_t Index = 0;
144925d7b4fbSAlexey Lapshin 
145025d7b4fbSAlexey Lapshin   Expected<typename ELFFile<ELFT>::Elf_Phdr_Range> Headers =
145125d7b4fbSAlexey Lapshin       HeadersFile.program_headers();
145225d7b4fbSAlexey Lapshin   if (!Headers)
145325d7b4fbSAlexey Lapshin     return Headers.takeError();
145425d7b4fbSAlexey Lapshin 
145525d7b4fbSAlexey Lapshin   for (const typename ELFFile<ELFT>::Elf_Phdr &Phdr : *Headers) {
145625d7b4fbSAlexey Lapshin     if (Phdr.p_offset + Phdr.p_filesz > HeadersFile.getBufSize())
145725d7b4fbSAlexey Lapshin       return createStringError(
145825d7b4fbSAlexey Lapshin           errc::invalid_argument,
145925d7b4fbSAlexey Lapshin           "program header with offset 0x" + Twine::utohexstr(Phdr.p_offset) +
146025d7b4fbSAlexey Lapshin               " and file size 0x" + Twine::utohexstr(Phdr.p_filesz) +
146125d7b4fbSAlexey Lapshin               " goes past the end of the file");
146225d7b4fbSAlexey Lapshin 
146325d7b4fbSAlexey Lapshin     ArrayRef<uint8_t> Data{HeadersFile.base() + Phdr.p_offset,
146425d7b4fbSAlexey Lapshin                            (size_t)Phdr.p_filesz};
146525d7b4fbSAlexey Lapshin     Segment &Seg = Obj.addSegment(Data);
146625d7b4fbSAlexey Lapshin     Seg.Type = Phdr.p_type;
146725d7b4fbSAlexey Lapshin     Seg.Flags = Phdr.p_flags;
146825d7b4fbSAlexey Lapshin     Seg.OriginalOffset = Phdr.p_offset + EhdrOffset;
146925d7b4fbSAlexey Lapshin     Seg.Offset = Phdr.p_offset + EhdrOffset;
147025d7b4fbSAlexey Lapshin     Seg.VAddr = Phdr.p_vaddr;
147125d7b4fbSAlexey Lapshin     Seg.PAddr = Phdr.p_paddr;
147225d7b4fbSAlexey Lapshin     Seg.FileSize = Phdr.p_filesz;
147325d7b4fbSAlexey Lapshin     Seg.MemSize = Phdr.p_memsz;
147425d7b4fbSAlexey Lapshin     Seg.Align = Phdr.p_align;
147525d7b4fbSAlexey Lapshin     Seg.Index = Index++;
147625d7b4fbSAlexey Lapshin     for (SectionBase &Sec : Obj.sections())
147725d7b4fbSAlexey Lapshin       if (sectionWithinSegment(Sec, Seg)) {
147825d7b4fbSAlexey Lapshin         Seg.addSection(&Sec);
147925d7b4fbSAlexey Lapshin         if (!Sec.ParentSegment || Sec.ParentSegment->Offset > Seg.Offset)
148025d7b4fbSAlexey Lapshin           Sec.ParentSegment = &Seg;
148125d7b4fbSAlexey Lapshin       }
148225d7b4fbSAlexey Lapshin   }
148325d7b4fbSAlexey Lapshin 
148425d7b4fbSAlexey Lapshin   auto &ElfHdr = Obj.ElfHdrSegment;
148525d7b4fbSAlexey Lapshin   ElfHdr.Index = Index++;
148625d7b4fbSAlexey Lapshin   ElfHdr.OriginalOffset = ElfHdr.Offset = EhdrOffset;
148725d7b4fbSAlexey Lapshin 
148825d7b4fbSAlexey Lapshin   const typename ELFT::Ehdr &Ehdr = HeadersFile.getHeader();
148925d7b4fbSAlexey Lapshin   auto &PrHdr = Obj.ProgramHdrSegment;
149025d7b4fbSAlexey Lapshin   PrHdr.Type = PT_PHDR;
149125d7b4fbSAlexey Lapshin   PrHdr.Flags = 0;
149225d7b4fbSAlexey Lapshin   // The spec requires us to have p_vaddr % p_align == p_offset % p_align.
149325d7b4fbSAlexey Lapshin   // Whereas this works automatically for ElfHdr, here OriginalOffset is
149425d7b4fbSAlexey Lapshin   // always non-zero and to ensure the equation we assign the same value to
149525d7b4fbSAlexey Lapshin   // VAddr as well.
149625d7b4fbSAlexey Lapshin   PrHdr.OriginalOffset = PrHdr.Offset = PrHdr.VAddr = EhdrOffset + Ehdr.e_phoff;
149725d7b4fbSAlexey Lapshin   PrHdr.PAddr = 0;
149825d7b4fbSAlexey Lapshin   PrHdr.FileSize = PrHdr.MemSize = Ehdr.e_phentsize * Ehdr.e_phnum;
149925d7b4fbSAlexey Lapshin   // The spec requires us to naturally align all the fields.
150025d7b4fbSAlexey Lapshin   PrHdr.Align = sizeof(Elf_Addr);
150125d7b4fbSAlexey Lapshin   PrHdr.Index = Index++;
150225d7b4fbSAlexey Lapshin 
150325d7b4fbSAlexey Lapshin   // Now we do an O(n^2) loop through the segments in order to match up
150425d7b4fbSAlexey Lapshin   // segments.
150525d7b4fbSAlexey Lapshin   for (Segment &Child : Obj.segments())
150625d7b4fbSAlexey Lapshin     setParentSegment(Child);
150725d7b4fbSAlexey Lapshin   setParentSegment(ElfHdr);
150825d7b4fbSAlexey Lapshin   setParentSegment(PrHdr);
150925d7b4fbSAlexey Lapshin 
151025d7b4fbSAlexey Lapshin   return Error::success();
151125d7b4fbSAlexey Lapshin }
151225d7b4fbSAlexey Lapshin 
151325d7b4fbSAlexey Lapshin template <class ELFT>
151425d7b4fbSAlexey Lapshin Error ELFBuilder<ELFT>::initGroupSection(GroupSection *GroupSec) {
151525d7b4fbSAlexey Lapshin   if (GroupSec->Align % sizeof(ELF::Elf32_Word) != 0)
151625d7b4fbSAlexey Lapshin     return createStringError(errc::invalid_argument,
151725d7b4fbSAlexey Lapshin                              "invalid alignment " + Twine(GroupSec->Align) +
151825d7b4fbSAlexey Lapshin                                  " of group section '" + GroupSec->Name + "'");
151925d7b4fbSAlexey Lapshin   SectionTableRef SecTable = Obj.sections();
152025d7b4fbSAlexey Lapshin   if (GroupSec->Link != SHN_UNDEF) {
152125d7b4fbSAlexey Lapshin     auto SymTab = SecTable.template getSectionOfType<SymbolTableSection>(
152225d7b4fbSAlexey Lapshin         GroupSec->Link,
152325d7b4fbSAlexey Lapshin         "link field value '" + Twine(GroupSec->Link) + "' in section '" +
152425d7b4fbSAlexey Lapshin             GroupSec->Name + "' is invalid",
152525d7b4fbSAlexey Lapshin         "link field value '" + Twine(GroupSec->Link) + "' in section '" +
152625d7b4fbSAlexey Lapshin             GroupSec->Name + "' is not a symbol table");
152725d7b4fbSAlexey Lapshin     if (!SymTab)
152825d7b4fbSAlexey Lapshin       return SymTab.takeError();
152925d7b4fbSAlexey Lapshin 
153025d7b4fbSAlexey Lapshin     Expected<Symbol *> Sym = (*SymTab)->getSymbolByIndex(GroupSec->Info);
153125d7b4fbSAlexey Lapshin     if (!Sym)
153225d7b4fbSAlexey Lapshin       return createStringError(errc::invalid_argument,
153325d7b4fbSAlexey Lapshin                                "info field value '" + Twine(GroupSec->Info) +
153425d7b4fbSAlexey Lapshin                                    "' in section '" + GroupSec->Name +
153525d7b4fbSAlexey Lapshin                                    "' is not a valid symbol index");
153625d7b4fbSAlexey Lapshin     GroupSec->setSymTab(*SymTab);
153725d7b4fbSAlexey Lapshin     GroupSec->setSymbol(*Sym);
153825d7b4fbSAlexey Lapshin   }
153925d7b4fbSAlexey Lapshin   if (GroupSec->Contents.size() % sizeof(ELF::Elf32_Word) ||
154025d7b4fbSAlexey Lapshin       GroupSec->Contents.empty())
154125d7b4fbSAlexey Lapshin     return createStringError(errc::invalid_argument,
154225d7b4fbSAlexey Lapshin                              "the content of the section " + GroupSec->Name +
154325d7b4fbSAlexey Lapshin                                  " is malformed");
154425d7b4fbSAlexey Lapshin   const ELF::Elf32_Word *Word =
154525d7b4fbSAlexey Lapshin       reinterpret_cast<const ELF::Elf32_Word *>(GroupSec->Contents.data());
154625d7b4fbSAlexey Lapshin   const ELF::Elf32_Word *End =
154725d7b4fbSAlexey Lapshin       Word + GroupSec->Contents.size() / sizeof(ELF::Elf32_Word);
154827633538SFangrui Song   GroupSec->setFlagWord(endian::read32<ELFT::Endianness>(Word++));
154925d7b4fbSAlexey Lapshin   for (; Word != End; ++Word) {
155027633538SFangrui Song     uint32_t Index = support::endian::read32<ELFT::Endianness>(Word);
155125d7b4fbSAlexey Lapshin     Expected<SectionBase *> Sec = SecTable.getSection(
155225d7b4fbSAlexey Lapshin         Index, "group member index " + Twine(Index) + " in section '" +
155325d7b4fbSAlexey Lapshin                    GroupSec->Name + "' is invalid");
155425d7b4fbSAlexey Lapshin     if (!Sec)
155525d7b4fbSAlexey Lapshin       return Sec.takeError();
155625d7b4fbSAlexey Lapshin 
155725d7b4fbSAlexey Lapshin     GroupSec->addMember(*Sec);
155825d7b4fbSAlexey Lapshin   }
155925d7b4fbSAlexey Lapshin 
156025d7b4fbSAlexey Lapshin   return Error::success();
156125d7b4fbSAlexey Lapshin }
156225d7b4fbSAlexey Lapshin 
156325d7b4fbSAlexey Lapshin template <class ELFT>
156425d7b4fbSAlexey Lapshin Error ELFBuilder<ELFT>::initSymbolTable(SymbolTableSection *SymTab) {
156525d7b4fbSAlexey Lapshin   Expected<const Elf_Shdr *> Shdr = ElfFile.getSection(SymTab->Index);
156625d7b4fbSAlexey Lapshin   if (!Shdr)
156725d7b4fbSAlexey Lapshin     return Shdr.takeError();
156825d7b4fbSAlexey Lapshin 
156925d7b4fbSAlexey Lapshin   Expected<StringRef> StrTabData = ElfFile.getStringTableForSymtab(**Shdr);
157025d7b4fbSAlexey Lapshin   if (!StrTabData)
157125d7b4fbSAlexey Lapshin     return StrTabData.takeError();
157225d7b4fbSAlexey Lapshin 
157325d7b4fbSAlexey Lapshin   ArrayRef<Elf_Word> ShndxData;
157425d7b4fbSAlexey Lapshin 
157525d7b4fbSAlexey Lapshin   Expected<typename ELFFile<ELFT>::Elf_Sym_Range> Symbols =
157625d7b4fbSAlexey Lapshin       ElfFile.symbols(*Shdr);
157725d7b4fbSAlexey Lapshin   if (!Symbols)
157825d7b4fbSAlexey Lapshin     return Symbols.takeError();
157925d7b4fbSAlexey Lapshin 
158025d7b4fbSAlexey Lapshin   for (const typename ELFFile<ELFT>::Elf_Sym &Sym : *Symbols) {
158125d7b4fbSAlexey Lapshin     SectionBase *DefSection = nullptr;
158225d7b4fbSAlexey Lapshin 
158325d7b4fbSAlexey Lapshin     Expected<StringRef> Name = Sym.getName(*StrTabData);
158425d7b4fbSAlexey Lapshin     if (!Name)
158525d7b4fbSAlexey Lapshin       return Name.takeError();
158625d7b4fbSAlexey Lapshin 
158725d7b4fbSAlexey Lapshin     if (Sym.st_shndx == SHN_XINDEX) {
158825d7b4fbSAlexey Lapshin       if (SymTab->getShndxTable() == nullptr)
158925d7b4fbSAlexey Lapshin         return createStringError(errc::invalid_argument,
159025d7b4fbSAlexey Lapshin                                  "symbol '" + *Name +
159125d7b4fbSAlexey Lapshin                                      "' has index SHN_XINDEX but no "
159225d7b4fbSAlexey Lapshin                                      "SHT_SYMTAB_SHNDX section exists");
159325d7b4fbSAlexey Lapshin       if (ShndxData.data() == nullptr) {
159425d7b4fbSAlexey Lapshin         Expected<const Elf_Shdr *> ShndxSec =
159525d7b4fbSAlexey Lapshin             ElfFile.getSection(SymTab->getShndxTable()->Index);
159625d7b4fbSAlexey Lapshin         if (!ShndxSec)
159725d7b4fbSAlexey Lapshin           return ShndxSec.takeError();
159825d7b4fbSAlexey Lapshin 
159925d7b4fbSAlexey Lapshin         Expected<ArrayRef<Elf_Word>> Data =
160025d7b4fbSAlexey Lapshin             ElfFile.template getSectionContentsAsArray<Elf_Word>(**ShndxSec);
160125d7b4fbSAlexey Lapshin         if (!Data)
160225d7b4fbSAlexey Lapshin           return Data.takeError();
160325d7b4fbSAlexey Lapshin 
160425d7b4fbSAlexey Lapshin         ShndxData = *Data;
160525d7b4fbSAlexey Lapshin         if (ShndxData.size() != Symbols->size())
160625d7b4fbSAlexey Lapshin           return createStringError(
160725d7b4fbSAlexey Lapshin               errc::invalid_argument,
160825d7b4fbSAlexey Lapshin               "symbol section index table does not have the same number of "
160925d7b4fbSAlexey Lapshin               "entries as the symbol table");
161025d7b4fbSAlexey Lapshin       }
161125d7b4fbSAlexey Lapshin       Elf_Word Index = ShndxData[&Sym - Symbols->begin()];
161225d7b4fbSAlexey Lapshin       Expected<SectionBase *> Sec = Obj.sections().getSection(
161325d7b4fbSAlexey Lapshin           Index,
161425d7b4fbSAlexey Lapshin           "symbol '" + *Name + "' has invalid section index " + Twine(Index));
161525d7b4fbSAlexey Lapshin       if (!Sec)
161625d7b4fbSAlexey Lapshin         return Sec.takeError();
161725d7b4fbSAlexey Lapshin 
161825d7b4fbSAlexey Lapshin       DefSection = *Sec;
161925d7b4fbSAlexey Lapshin     } else if (Sym.st_shndx >= SHN_LORESERVE) {
162025d7b4fbSAlexey Lapshin       if (!isValidReservedSectionIndex(Sym.st_shndx, Obj.Machine)) {
162125d7b4fbSAlexey Lapshin         return createStringError(
162225d7b4fbSAlexey Lapshin             errc::invalid_argument,
162325d7b4fbSAlexey Lapshin             "symbol '" + *Name +
162425d7b4fbSAlexey Lapshin                 "' has unsupported value greater than or equal "
162525d7b4fbSAlexey Lapshin                 "to SHN_LORESERVE: " +
162625d7b4fbSAlexey Lapshin                 Twine(Sym.st_shndx));
162725d7b4fbSAlexey Lapshin       }
162825d7b4fbSAlexey Lapshin     } else if (Sym.st_shndx != SHN_UNDEF) {
162925d7b4fbSAlexey Lapshin       Expected<SectionBase *> Sec = Obj.sections().getSection(
163025d7b4fbSAlexey Lapshin           Sym.st_shndx, "symbol '" + *Name +
163125d7b4fbSAlexey Lapshin                             "' is defined has invalid section index " +
163225d7b4fbSAlexey Lapshin                             Twine(Sym.st_shndx));
163325d7b4fbSAlexey Lapshin       if (!Sec)
163425d7b4fbSAlexey Lapshin         return Sec.takeError();
163525d7b4fbSAlexey Lapshin 
163625d7b4fbSAlexey Lapshin       DefSection = *Sec;
163725d7b4fbSAlexey Lapshin     }
163825d7b4fbSAlexey Lapshin 
163925d7b4fbSAlexey Lapshin     SymTab->addSymbol(*Name, Sym.getBinding(), Sym.getType(), DefSection,
164025d7b4fbSAlexey Lapshin                       Sym.getValue(), Sym.st_other, Sym.st_shndx, Sym.st_size);
164125d7b4fbSAlexey Lapshin   }
164225d7b4fbSAlexey Lapshin 
164325d7b4fbSAlexey Lapshin   return Error::success();
164425d7b4fbSAlexey Lapshin }
164525d7b4fbSAlexey Lapshin 
164625d7b4fbSAlexey Lapshin template <class ELFT>
164725d7b4fbSAlexey Lapshin static void getAddend(uint64_t &, const Elf_Rel_Impl<ELFT, false> &) {}
164825d7b4fbSAlexey Lapshin 
164925d7b4fbSAlexey Lapshin template <class ELFT>
165025d7b4fbSAlexey Lapshin static void getAddend(uint64_t &ToSet, const Elf_Rel_Impl<ELFT, true> &Rela) {
165125d7b4fbSAlexey Lapshin   ToSet = Rela.r_addend;
165225d7b4fbSAlexey Lapshin }
165325d7b4fbSAlexey Lapshin 
165425d7b4fbSAlexey Lapshin template <class T>
165525d7b4fbSAlexey Lapshin static Error initRelocations(RelocationSection *Relocs, T RelRange) {
165625d7b4fbSAlexey Lapshin   for (const auto &Rel : RelRange) {
165725d7b4fbSAlexey Lapshin     Relocation ToAdd;
165825d7b4fbSAlexey Lapshin     ToAdd.Offset = Rel.r_offset;
165925d7b4fbSAlexey Lapshin     getAddend(ToAdd.Addend, Rel);
166025d7b4fbSAlexey Lapshin     ToAdd.Type = Rel.getType(Relocs->getObject().IsMips64EL);
166125d7b4fbSAlexey Lapshin 
166225d7b4fbSAlexey Lapshin     if (uint32_t Sym = Rel.getSymbol(Relocs->getObject().IsMips64EL)) {
166325d7b4fbSAlexey Lapshin       if (!Relocs->getObject().SymbolTable)
166425d7b4fbSAlexey Lapshin         return createStringError(
166525d7b4fbSAlexey Lapshin             errc::invalid_argument,
166625d7b4fbSAlexey Lapshin             "'" + Relocs->Name + "': relocation references symbol with index " +
166725d7b4fbSAlexey Lapshin                 Twine(Sym) + ", but there is no symbol table");
166825d7b4fbSAlexey Lapshin       Expected<Symbol *> SymByIndex =
166925d7b4fbSAlexey Lapshin           Relocs->getObject().SymbolTable->getSymbolByIndex(Sym);
167025d7b4fbSAlexey Lapshin       if (!SymByIndex)
167125d7b4fbSAlexey Lapshin         return SymByIndex.takeError();
167225d7b4fbSAlexey Lapshin 
167325d7b4fbSAlexey Lapshin       ToAdd.RelocSymbol = *SymByIndex;
167425d7b4fbSAlexey Lapshin     }
167525d7b4fbSAlexey Lapshin 
167625d7b4fbSAlexey Lapshin     Relocs->addRelocation(ToAdd);
167725d7b4fbSAlexey Lapshin   }
167825d7b4fbSAlexey Lapshin 
167925d7b4fbSAlexey Lapshin   return Error::success();
168025d7b4fbSAlexey Lapshin }
168125d7b4fbSAlexey Lapshin 
168225d7b4fbSAlexey Lapshin Expected<SectionBase *> SectionTableRef::getSection(uint32_t Index,
168325d7b4fbSAlexey Lapshin                                                     Twine ErrMsg) {
168425d7b4fbSAlexey Lapshin   if (Index == SHN_UNDEF || Index > Sections.size())
168525d7b4fbSAlexey Lapshin     return createStringError(errc::invalid_argument, ErrMsg);
168625d7b4fbSAlexey Lapshin   return Sections[Index - 1].get();
168725d7b4fbSAlexey Lapshin }
168825d7b4fbSAlexey Lapshin 
168925d7b4fbSAlexey Lapshin template <class T>
169025d7b4fbSAlexey Lapshin Expected<T *> SectionTableRef::getSectionOfType(uint32_t Index,
169125d7b4fbSAlexey Lapshin                                                 Twine IndexErrMsg,
169225d7b4fbSAlexey Lapshin                                                 Twine TypeErrMsg) {
169325d7b4fbSAlexey Lapshin   Expected<SectionBase *> BaseSec = getSection(Index, IndexErrMsg);
169425d7b4fbSAlexey Lapshin   if (!BaseSec)
169525d7b4fbSAlexey Lapshin     return BaseSec.takeError();
169625d7b4fbSAlexey Lapshin 
169725d7b4fbSAlexey Lapshin   if (T *Sec = dyn_cast<T>(*BaseSec))
169825d7b4fbSAlexey Lapshin     return Sec;
169925d7b4fbSAlexey Lapshin 
170025d7b4fbSAlexey Lapshin   return createStringError(errc::invalid_argument, TypeErrMsg);
170125d7b4fbSAlexey Lapshin }
170225d7b4fbSAlexey Lapshin 
170325d7b4fbSAlexey Lapshin template <class ELFT>
170425d7b4fbSAlexey Lapshin Expected<SectionBase &> ELFBuilder<ELFT>::makeSection(const Elf_Shdr &Shdr) {
170525d7b4fbSAlexey Lapshin   switch (Shdr.sh_type) {
170625d7b4fbSAlexey Lapshin   case SHT_REL:
170725d7b4fbSAlexey Lapshin   case SHT_RELA:
17089bb4cd59SFangrui Song   case SHT_CREL:
170925d7b4fbSAlexey Lapshin     if (Shdr.sh_flags & SHF_ALLOC) {
171025d7b4fbSAlexey Lapshin       if (Expected<ArrayRef<uint8_t>> Data = ElfFile.getSectionContents(Shdr))
171125d7b4fbSAlexey Lapshin         return Obj.addSection<DynamicRelocationSection>(*Data);
171225d7b4fbSAlexey Lapshin       else
171325d7b4fbSAlexey Lapshin         return Data.takeError();
171425d7b4fbSAlexey Lapshin     }
171525d7b4fbSAlexey Lapshin     return Obj.addSection<RelocationSection>(Obj);
171625d7b4fbSAlexey Lapshin   case SHT_STRTAB:
171725d7b4fbSAlexey Lapshin     // If a string table is allocated we don't want to mess with it. That would
171825d7b4fbSAlexey Lapshin     // mean altering the memory image. There are no special link types or
171925d7b4fbSAlexey Lapshin     // anything so we can just use a Section.
172025d7b4fbSAlexey Lapshin     if (Shdr.sh_flags & SHF_ALLOC) {
172125d7b4fbSAlexey Lapshin       if (Expected<ArrayRef<uint8_t>> Data = ElfFile.getSectionContents(Shdr))
172225d7b4fbSAlexey Lapshin         return Obj.addSection<Section>(*Data);
172325d7b4fbSAlexey Lapshin       else
172425d7b4fbSAlexey Lapshin         return Data.takeError();
172525d7b4fbSAlexey Lapshin     }
172625d7b4fbSAlexey Lapshin     return Obj.addSection<StringTableSection>();
172725d7b4fbSAlexey Lapshin   case SHT_HASH:
172825d7b4fbSAlexey Lapshin   case SHT_GNU_HASH:
172925d7b4fbSAlexey Lapshin     // Hash tables should refer to SHT_DYNSYM which we're not going to change.
173025d7b4fbSAlexey Lapshin     // Because of this we don't need to mess with the hash tables either.
173125d7b4fbSAlexey Lapshin     if (Expected<ArrayRef<uint8_t>> Data = ElfFile.getSectionContents(Shdr))
173225d7b4fbSAlexey Lapshin       return Obj.addSection<Section>(*Data);
173325d7b4fbSAlexey Lapshin     else
173425d7b4fbSAlexey Lapshin       return Data.takeError();
173525d7b4fbSAlexey Lapshin   case SHT_GROUP:
173625d7b4fbSAlexey Lapshin     if (Expected<ArrayRef<uint8_t>> Data = ElfFile.getSectionContents(Shdr))
173725d7b4fbSAlexey Lapshin       return Obj.addSection<GroupSection>(*Data);
173825d7b4fbSAlexey Lapshin     else
173925d7b4fbSAlexey Lapshin       return Data.takeError();
174025d7b4fbSAlexey Lapshin   case SHT_DYNSYM:
174125d7b4fbSAlexey Lapshin     if (Expected<ArrayRef<uint8_t>> Data = ElfFile.getSectionContents(Shdr))
174225d7b4fbSAlexey Lapshin       return Obj.addSection<DynamicSymbolTableSection>(*Data);
174325d7b4fbSAlexey Lapshin     else
174425d7b4fbSAlexey Lapshin       return Data.takeError();
174525d7b4fbSAlexey Lapshin   case SHT_DYNAMIC:
174625d7b4fbSAlexey Lapshin     if (Expected<ArrayRef<uint8_t>> Data = ElfFile.getSectionContents(Shdr))
174725d7b4fbSAlexey Lapshin       return Obj.addSection<DynamicSection>(*Data);
174825d7b4fbSAlexey Lapshin     else
174925d7b4fbSAlexey Lapshin       return Data.takeError();
175025d7b4fbSAlexey Lapshin   case SHT_SYMTAB: {
1751bc6e10c9SMoshe Berman     // Multiple SHT_SYMTAB sections are forbidden by the ELF gABI.
1752bc6e10c9SMoshe Berman     if (Obj.SymbolTable != nullptr)
1753bc6e10c9SMoshe Berman       return createStringError(llvm::errc::invalid_argument,
1754bc6e10c9SMoshe Berman                                "found multiple SHT_SYMTAB sections");
175525d7b4fbSAlexey Lapshin     auto &SymTab = Obj.addSection<SymbolTableSection>();
175625d7b4fbSAlexey Lapshin     Obj.SymbolTable = &SymTab;
175725d7b4fbSAlexey Lapshin     return SymTab;
175825d7b4fbSAlexey Lapshin   }
175925d7b4fbSAlexey Lapshin   case SHT_SYMTAB_SHNDX: {
176025d7b4fbSAlexey Lapshin     auto &ShndxSection = Obj.addSection<SectionIndexSection>();
176125d7b4fbSAlexey Lapshin     Obj.SectionIndexTable = &ShndxSection;
176225d7b4fbSAlexey Lapshin     return ShndxSection;
176325d7b4fbSAlexey Lapshin   }
176425d7b4fbSAlexey Lapshin   case SHT_NOBITS:
176525d7b4fbSAlexey Lapshin     return Obj.addSection<Section>(ArrayRef<uint8_t>());
176625d7b4fbSAlexey Lapshin   default: {
176725d7b4fbSAlexey Lapshin     Expected<ArrayRef<uint8_t>> Data = ElfFile.getSectionContents(Shdr);
176825d7b4fbSAlexey Lapshin     if (!Data)
176925d7b4fbSAlexey Lapshin       return Data.takeError();
177025d7b4fbSAlexey Lapshin 
177125d7b4fbSAlexey Lapshin     Expected<StringRef> Name = ElfFile.getSectionName(Shdr);
177225d7b4fbSAlexey Lapshin     if (!Name)
177325d7b4fbSAlexey Lapshin       return Name.takeError();
177425d7b4fbSAlexey Lapshin 
177591e2cd4fSFangrui Song     if (!(Shdr.sh_flags & ELF::SHF_COMPRESSED))
177625d7b4fbSAlexey Lapshin       return Obj.addSection<Section>(*Data);
177791e2cd4fSFangrui Song     auto *Chdr = reinterpret_cast<const Elf_Chdr_Impl<ELFT> *>(Data->data());
1778b6e1fd76SFangrui Song     return Obj.addSection<CompressedSection>(CompressedSection(
1779b6e1fd76SFangrui Song         *Data, Chdr->ch_type, Chdr->ch_size, Chdr->ch_addralign));
178025d7b4fbSAlexey Lapshin   }
178125d7b4fbSAlexey Lapshin   }
178225d7b4fbSAlexey Lapshin }
178325d7b4fbSAlexey Lapshin 
178425d7b4fbSAlexey Lapshin template <class ELFT> Error ELFBuilder<ELFT>::readSectionHeaders() {
178525d7b4fbSAlexey Lapshin   uint32_t Index = 0;
178625d7b4fbSAlexey Lapshin   Expected<typename ELFFile<ELFT>::Elf_Shdr_Range> Sections =
178725d7b4fbSAlexey Lapshin       ElfFile.sections();
178825d7b4fbSAlexey Lapshin   if (!Sections)
178925d7b4fbSAlexey Lapshin     return Sections.takeError();
179025d7b4fbSAlexey Lapshin 
179125d7b4fbSAlexey Lapshin   for (const typename ELFFile<ELFT>::Elf_Shdr &Shdr : *Sections) {
179225d7b4fbSAlexey Lapshin     if (Index == 0) {
179325d7b4fbSAlexey Lapshin       ++Index;
179425d7b4fbSAlexey Lapshin       continue;
179525d7b4fbSAlexey Lapshin     }
179625d7b4fbSAlexey Lapshin     Expected<SectionBase &> Sec = makeSection(Shdr);
179725d7b4fbSAlexey Lapshin     if (!Sec)
179825d7b4fbSAlexey Lapshin       return Sec.takeError();
179925d7b4fbSAlexey Lapshin 
180025d7b4fbSAlexey Lapshin     Expected<StringRef> SecName = ElfFile.getSectionName(Shdr);
180125d7b4fbSAlexey Lapshin     if (!SecName)
180225d7b4fbSAlexey Lapshin       return SecName.takeError();
180325d7b4fbSAlexey Lapshin     Sec->Name = SecName->str();
180425d7b4fbSAlexey Lapshin     Sec->Type = Sec->OriginalType = Shdr.sh_type;
180525d7b4fbSAlexey Lapshin     Sec->Flags = Sec->OriginalFlags = Shdr.sh_flags;
180625d7b4fbSAlexey Lapshin     Sec->Addr = Shdr.sh_addr;
180725d7b4fbSAlexey Lapshin     Sec->Offset = Shdr.sh_offset;
180825d7b4fbSAlexey Lapshin     Sec->OriginalOffset = Shdr.sh_offset;
180925d7b4fbSAlexey Lapshin     Sec->Size = Shdr.sh_size;
181025d7b4fbSAlexey Lapshin     Sec->Link = Shdr.sh_link;
181125d7b4fbSAlexey Lapshin     Sec->Info = Shdr.sh_info;
181225d7b4fbSAlexey Lapshin     Sec->Align = Shdr.sh_addralign;
181325d7b4fbSAlexey Lapshin     Sec->EntrySize = Shdr.sh_entsize;
181425d7b4fbSAlexey Lapshin     Sec->Index = Index++;
181525d7b4fbSAlexey Lapshin     Sec->OriginalIndex = Sec->Index;
181625d7b4fbSAlexey Lapshin     Sec->OriginalData = ArrayRef<uint8_t>(
181725d7b4fbSAlexey Lapshin         ElfFile.base() + Shdr.sh_offset,
181825d7b4fbSAlexey Lapshin         (Shdr.sh_type == SHT_NOBITS) ? (size_t)0 : Shdr.sh_size);
181925d7b4fbSAlexey Lapshin   }
182025d7b4fbSAlexey Lapshin 
182125d7b4fbSAlexey Lapshin   return Error::success();
182225d7b4fbSAlexey Lapshin }
182325d7b4fbSAlexey Lapshin 
182425d7b4fbSAlexey Lapshin template <class ELFT> Error ELFBuilder<ELFT>::readSections(bool EnsureSymtab) {
182525d7b4fbSAlexey Lapshin   uint32_t ShstrIndex = ElfFile.getHeader().e_shstrndx;
182625d7b4fbSAlexey Lapshin   if (ShstrIndex == SHN_XINDEX) {
182725d7b4fbSAlexey Lapshin     Expected<const Elf_Shdr *> Sec = ElfFile.getSection(0);
182825d7b4fbSAlexey Lapshin     if (!Sec)
182925d7b4fbSAlexey Lapshin       return Sec.takeError();
183025d7b4fbSAlexey Lapshin 
183125d7b4fbSAlexey Lapshin     ShstrIndex = (*Sec)->sh_link;
183225d7b4fbSAlexey Lapshin   }
183325d7b4fbSAlexey Lapshin 
183425d7b4fbSAlexey Lapshin   if (ShstrIndex == SHN_UNDEF)
183525d7b4fbSAlexey Lapshin     Obj.HadShdrs = false;
183625d7b4fbSAlexey Lapshin   else {
183725d7b4fbSAlexey Lapshin     Expected<StringTableSection *> Sec =
183825d7b4fbSAlexey Lapshin         Obj.sections().template getSectionOfType<StringTableSection>(
183925d7b4fbSAlexey Lapshin             ShstrIndex,
184025d7b4fbSAlexey Lapshin             "e_shstrndx field value " + Twine(ShstrIndex) + " in elf header " +
184125d7b4fbSAlexey Lapshin                 " is invalid",
184225d7b4fbSAlexey Lapshin             "e_shstrndx field value " + Twine(ShstrIndex) + " in elf header " +
184325d7b4fbSAlexey Lapshin                 " does not reference a string table");
184425d7b4fbSAlexey Lapshin     if (!Sec)
184525d7b4fbSAlexey Lapshin       return Sec.takeError();
184625d7b4fbSAlexey Lapshin 
184725d7b4fbSAlexey Lapshin     Obj.SectionNames = *Sec;
184825d7b4fbSAlexey Lapshin   }
184925d7b4fbSAlexey Lapshin 
185025d7b4fbSAlexey Lapshin   // If a section index table exists we'll need to initialize it before we
185125d7b4fbSAlexey Lapshin   // initialize the symbol table because the symbol table might need to
185225d7b4fbSAlexey Lapshin   // reference it.
185325d7b4fbSAlexey Lapshin   if (Obj.SectionIndexTable)
185425d7b4fbSAlexey Lapshin     if (Error Err = Obj.SectionIndexTable->initialize(Obj.sections()))
185525d7b4fbSAlexey Lapshin       return Err;
185625d7b4fbSAlexey Lapshin 
185725d7b4fbSAlexey Lapshin   // Now that all of the sections have been added we can fill out some extra
185825d7b4fbSAlexey Lapshin   // details about symbol tables. We need the symbol table filled out before
185925d7b4fbSAlexey Lapshin   // any relocations.
186025d7b4fbSAlexey Lapshin   if (Obj.SymbolTable) {
186125d7b4fbSAlexey Lapshin     if (Error Err = Obj.SymbolTable->initialize(Obj.sections()))
186225d7b4fbSAlexey Lapshin       return Err;
186325d7b4fbSAlexey Lapshin     if (Error Err = initSymbolTable(Obj.SymbolTable))
186425d7b4fbSAlexey Lapshin       return Err;
186525d7b4fbSAlexey Lapshin   } else if (EnsureSymtab) {
186625d7b4fbSAlexey Lapshin     if (Error Err = Obj.addNewSymbolTable())
186725d7b4fbSAlexey Lapshin       return Err;
186825d7b4fbSAlexey Lapshin   }
186925d7b4fbSAlexey Lapshin 
187025d7b4fbSAlexey Lapshin   // Now that all sections and symbols have been added we can add
187125d7b4fbSAlexey Lapshin   // relocations that reference symbols and set the link and info fields for
187225d7b4fbSAlexey Lapshin   // relocation sections.
187325d7b4fbSAlexey Lapshin   for (SectionBase &Sec : Obj.sections()) {
187425d7b4fbSAlexey Lapshin     if (&Sec == Obj.SymbolTable)
187525d7b4fbSAlexey Lapshin       continue;
187625d7b4fbSAlexey Lapshin     if (Error Err = Sec.initialize(Obj.sections()))
187725d7b4fbSAlexey Lapshin       return Err;
187825d7b4fbSAlexey Lapshin     if (auto RelSec = dyn_cast<RelocationSection>(&Sec)) {
187925d7b4fbSAlexey Lapshin       Expected<typename ELFFile<ELFT>::Elf_Shdr_Range> Sections =
188025d7b4fbSAlexey Lapshin           ElfFile.sections();
188125d7b4fbSAlexey Lapshin       if (!Sections)
188225d7b4fbSAlexey Lapshin         return Sections.takeError();
188325d7b4fbSAlexey Lapshin 
188425d7b4fbSAlexey Lapshin       const typename ELFFile<ELFT>::Elf_Shdr *Shdr =
188525d7b4fbSAlexey Lapshin           Sections->begin() + RelSec->Index;
18869bb4cd59SFangrui Song       if (RelSec->Type == SHT_CREL) {
18879bb4cd59SFangrui Song         auto RelsOrRelas = ElfFile.crels(*Shdr);
18889bb4cd59SFangrui Song         if (!RelsOrRelas)
18899bb4cd59SFangrui Song           return RelsOrRelas.takeError();
18909bb4cd59SFangrui Song         if (Error Err = initRelocations(RelSec, RelsOrRelas->first))
18919bb4cd59SFangrui Song           return Err;
18929bb4cd59SFangrui Song         if (Error Err = initRelocations(RelSec, RelsOrRelas->second))
18939bb4cd59SFangrui Song           return Err;
18949bb4cd59SFangrui Song       } else if (RelSec->Type == SHT_REL) {
189525d7b4fbSAlexey Lapshin         Expected<typename ELFFile<ELFT>::Elf_Rel_Range> Rels =
189625d7b4fbSAlexey Lapshin             ElfFile.rels(*Shdr);
189725d7b4fbSAlexey Lapshin         if (!Rels)
189825d7b4fbSAlexey Lapshin           return Rels.takeError();
189925d7b4fbSAlexey Lapshin 
190025d7b4fbSAlexey Lapshin         if (Error Err = initRelocations(RelSec, *Rels))
190125d7b4fbSAlexey Lapshin           return Err;
190225d7b4fbSAlexey Lapshin       } else {
190325d7b4fbSAlexey Lapshin         Expected<typename ELFFile<ELFT>::Elf_Rela_Range> Relas =
190425d7b4fbSAlexey Lapshin             ElfFile.relas(*Shdr);
190525d7b4fbSAlexey Lapshin         if (!Relas)
190625d7b4fbSAlexey Lapshin           return Relas.takeError();
190725d7b4fbSAlexey Lapshin 
190825d7b4fbSAlexey Lapshin         if (Error Err = initRelocations(RelSec, *Relas))
190925d7b4fbSAlexey Lapshin           return Err;
191025d7b4fbSAlexey Lapshin       }
191125d7b4fbSAlexey Lapshin     } else if (auto GroupSec = dyn_cast<GroupSection>(&Sec)) {
191225d7b4fbSAlexey Lapshin       if (Error Err = initGroupSection(GroupSec))
191325d7b4fbSAlexey Lapshin         return Err;
191425d7b4fbSAlexey Lapshin     }
191525d7b4fbSAlexey Lapshin   }
191625d7b4fbSAlexey Lapshin 
191725d7b4fbSAlexey Lapshin   return Error::success();
191825d7b4fbSAlexey Lapshin }
191925d7b4fbSAlexey Lapshin 
192025d7b4fbSAlexey Lapshin template <class ELFT> Error ELFBuilder<ELFT>::build(bool EnsureSymtab) {
192125d7b4fbSAlexey Lapshin   if (Error E = readSectionHeaders())
192225d7b4fbSAlexey Lapshin     return E;
192325d7b4fbSAlexey Lapshin   if (Error E = findEhdrOffset())
192425d7b4fbSAlexey Lapshin     return E;
192525d7b4fbSAlexey Lapshin 
192625d7b4fbSAlexey Lapshin   // The ELFFile whose ELF headers and program headers are copied into the
192725d7b4fbSAlexey Lapshin   // output file. Normally the same as ElfFile, but if we're extracting a
192825d7b4fbSAlexey Lapshin   // loadable partition it will point to the partition's headers.
192925d7b4fbSAlexey Lapshin   Expected<ELFFile<ELFT>> HeadersFile = ELFFile<ELFT>::create(toStringRef(
193025d7b4fbSAlexey Lapshin       {ElfFile.base() + EhdrOffset, ElfFile.getBufSize() - EhdrOffset}));
193125d7b4fbSAlexey Lapshin   if (!HeadersFile)
193225d7b4fbSAlexey Lapshin     return HeadersFile.takeError();
193325d7b4fbSAlexey Lapshin 
193425d7b4fbSAlexey Lapshin   const typename ELFFile<ELFT>::Elf_Ehdr &Ehdr = HeadersFile->getHeader();
1935c997fe65SFangrui Song   Obj.Is64Bits = Ehdr.e_ident[EI_CLASS] == ELFCLASS64;
193625d7b4fbSAlexey Lapshin   Obj.OSABI = Ehdr.e_ident[EI_OSABI];
193725d7b4fbSAlexey Lapshin   Obj.ABIVersion = Ehdr.e_ident[EI_ABIVERSION];
193825d7b4fbSAlexey Lapshin   Obj.Type = Ehdr.e_type;
193925d7b4fbSAlexey Lapshin   Obj.Machine = Ehdr.e_machine;
194025d7b4fbSAlexey Lapshin   Obj.Version = Ehdr.e_version;
194125d7b4fbSAlexey Lapshin   Obj.Entry = Ehdr.e_entry;
194225d7b4fbSAlexey Lapshin   Obj.Flags = Ehdr.e_flags;
194325d7b4fbSAlexey Lapshin 
194425d7b4fbSAlexey Lapshin   if (Error E = readSections(EnsureSymtab))
194525d7b4fbSAlexey Lapshin     return E;
194625d7b4fbSAlexey Lapshin   return readProgramHeaders(*HeadersFile);
194725d7b4fbSAlexey Lapshin }
194825d7b4fbSAlexey Lapshin 
1949c008e92bSKazu Hirata Writer::~Writer() = default;
195025d7b4fbSAlexey Lapshin 
1951c008e92bSKazu Hirata Reader::~Reader() = default;
195225d7b4fbSAlexey Lapshin 
195325d7b4fbSAlexey Lapshin Expected<std::unique_ptr<Object>>
195425d7b4fbSAlexey Lapshin BinaryReader::create(bool /*EnsureSymtab*/) const {
195525d7b4fbSAlexey Lapshin   return BinaryELFBuilder(MemBuf, NewSymbolVisibility).build();
195625d7b4fbSAlexey Lapshin }
195725d7b4fbSAlexey Lapshin 
195825d7b4fbSAlexey Lapshin Expected<std::vector<IHexRecord>> IHexReader::parse() const {
195925d7b4fbSAlexey Lapshin   SmallVector<StringRef, 16> Lines;
196025d7b4fbSAlexey Lapshin   std::vector<IHexRecord> Records;
196125d7b4fbSAlexey Lapshin   bool HasSections = false;
196225d7b4fbSAlexey Lapshin 
196325d7b4fbSAlexey Lapshin   MemBuf->getBuffer().split(Lines, '\n');
196425d7b4fbSAlexey Lapshin   Records.reserve(Lines.size());
196525d7b4fbSAlexey Lapshin   for (size_t LineNo = 1; LineNo <= Lines.size(); ++LineNo) {
196625d7b4fbSAlexey Lapshin     StringRef Line = Lines[LineNo - 1].trim();
196725d7b4fbSAlexey Lapshin     if (Line.empty())
196825d7b4fbSAlexey Lapshin       continue;
196925d7b4fbSAlexey Lapshin 
197025d7b4fbSAlexey Lapshin     Expected<IHexRecord> R = IHexRecord::parse(Line);
197125d7b4fbSAlexey Lapshin     if (!R)
197225d7b4fbSAlexey Lapshin       return parseError(LineNo, R.takeError());
197325d7b4fbSAlexey Lapshin     if (R->Type == IHexRecord::EndOfFile)
197425d7b4fbSAlexey Lapshin       break;
197525d7b4fbSAlexey Lapshin     HasSections |= (R->Type == IHexRecord::Data);
197625d7b4fbSAlexey Lapshin     Records.push_back(*R);
197725d7b4fbSAlexey Lapshin   }
197825d7b4fbSAlexey Lapshin   if (!HasSections)
197925d7b4fbSAlexey Lapshin     return parseError(-1U, "no sections");
198025d7b4fbSAlexey Lapshin 
198125d7b4fbSAlexey Lapshin   return std::move(Records);
198225d7b4fbSAlexey Lapshin }
198325d7b4fbSAlexey Lapshin 
198425d7b4fbSAlexey Lapshin Expected<std::unique_ptr<Object>>
198525d7b4fbSAlexey Lapshin IHexReader::create(bool /*EnsureSymtab*/) const {
198625d7b4fbSAlexey Lapshin   Expected<std::vector<IHexRecord>> Records = parse();
198725d7b4fbSAlexey Lapshin   if (!Records)
198825d7b4fbSAlexey Lapshin     return Records.takeError();
198925d7b4fbSAlexey Lapshin 
199025d7b4fbSAlexey Lapshin   return IHexELFBuilder(*Records).build();
199125d7b4fbSAlexey Lapshin }
199225d7b4fbSAlexey Lapshin 
199325d7b4fbSAlexey Lapshin Expected<std::unique_ptr<Object>> ELFReader::create(bool EnsureSymtab) const {
199425d7b4fbSAlexey Lapshin   auto Obj = std::make_unique<Object>();
199525d7b4fbSAlexey Lapshin   if (auto *O = dyn_cast<ELFObjectFile<ELF32LE>>(Bin)) {
199625d7b4fbSAlexey Lapshin     ELFBuilder<ELF32LE> Builder(*O, *Obj, ExtractPartition);
199725d7b4fbSAlexey Lapshin     if (Error Err = Builder.build(EnsureSymtab))
199825d7b4fbSAlexey Lapshin       return std::move(Err);
199925d7b4fbSAlexey Lapshin     return std::move(Obj);
200025d7b4fbSAlexey Lapshin   } else if (auto *O = dyn_cast<ELFObjectFile<ELF64LE>>(Bin)) {
200125d7b4fbSAlexey Lapshin     ELFBuilder<ELF64LE> Builder(*O, *Obj, ExtractPartition);
200225d7b4fbSAlexey Lapshin     if (Error Err = Builder.build(EnsureSymtab))
200325d7b4fbSAlexey Lapshin       return std::move(Err);
200425d7b4fbSAlexey Lapshin     return std::move(Obj);
200525d7b4fbSAlexey Lapshin   } else if (auto *O = dyn_cast<ELFObjectFile<ELF32BE>>(Bin)) {
200625d7b4fbSAlexey Lapshin     ELFBuilder<ELF32BE> Builder(*O, *Obj, ExtractPartition);
200725d7b4fbSAlexey Lapshin     if (Error Err = Builder.build(EnsureSymtab))
200825d7b4fbSAlexey Lapshin       return std::move(Err);
200925d7b4fbSAlexey Lapshin     return std::move(Obj);
201025d7b4fbSAlexey Lapshin   } else if (auto *O = dyn_cast<ELFObjectFile<ELF64BE>>(Bin)) {
201125d7b4fbSAlexey Lapshin     ELFBuilder<ELF64BE> Builder(*O, *Obj, ExtractPartition);
201225d7b4fbSAlexey Lapshin     if (Error Err = Builder.build(EnsureSymtab))
201325d7b4fbSAlexey Lapshin       return std::move(Err);
201425d7b4fbSAlexey Lapshin     return std::move(Obj);
201525d7b4fbSAlexey Lapshin   }
201625d7b4fbSAlexey Lapshin   return createStringError(errc::invalid_argument, "invalid file type");
201725d7b4fbSAlexey Lapshin }
201825d7b4fbSAlexey Lapshin 
201925d7b4fbSAlexey Lapshin template <class ELFT> void ELFWriter<ELFT>::writeEhdr() {
202025d7b4fbSAlexey Lapshin   Elf_Ehdr &Ehdr = *reinterpret_cast<Elf_Ehdr *>(Buf->getBufferStart());
202125d7b4fbSAlexey Lapshin   std::fill(Ehdr.e_ident, Ehdr.e_ident + 16, 0);
202225d7b4fbSAlexey Lapshin   Ehdr.e_ident[EI_MAG0] = 0x7f;
202325d7b4fbSAlexey Lapshin   Ehdr.e_ident[EI_MAG1] = 'E';
202425d7b4fbSAlexey Lapshin   Ehdr.e_ident[EI_MAG2] = 'L';
202525d7b4fbSAlexey Lapshin   Ehdr.e_ident[EI_MAG3] = 'F';
202625d7b4fbSAlexey Lapshin   Ehdr.e_ident[EI_CLASS] = ELFT::Is64Bits ? ELFCLASS64 : ELFCLASS32;
202727633538SFangrui Song   Ehdr.e_ident[EI_DATA] =
202827633538SFangrui Song       ELFT::Endianness == llvm::endianness::big ? ELFDATA2MSB : ELFDATA2LSB;
202925d7b4fbSAlexey Lapshin   Ehdr.e_ident[EI_VERSION] = EV_CURRENT;
203025d7b4fbSAlexey Lapshin   Ehdr.e_ident[EI_OSABI] = Obj.OSABI;
203125d7b4fbSAlexey Lapshin   Ehdr.e_ident[EI_ABIVERSION] = Obj.ABIVersion;
203225d7b4fbSAlexey Lapshin 
203325d7b4fbSAlexey Lapshin   Ehdr.e_type = Obj.Type;
203425d7b4fbSAlexey Lapshin   Ehdr.e_machine = Obj.Machine;
203525d7b4fbSAlexey Lapshin   Ehdr.e_version = Obj.Version;
203625d7b4fbSAlexey Lapshin   Ehdr.e_entry = Obj.Entry;
203725d7b4fbSAlexey Lapshin   // We have to use the fully-qualified name llvm::size
203825d7b4fbSAlexey Lapshin   // since some compilers complain on ambiguous resolution.
203925d7b4fbSAlexey Lapshin   Ehdr.e_phnum = llvm::size(Obj.segments());
204025d7b4fbSAlexey Lapshin   Ehdr.e_phoff = (Ehdr.e_phnum != 0) ? Obj.ProgramHdrSegment.Offset : 0;
204125d7b4fbSAlexey Lapshin   Ehdr.e_phentsize = (Ehdr.e_phnum != 0) ? sizeof(Elf_Phdr) : 0;
204225d7b4fbSAlexey Lapshin   Ehdr.e_flags = Obj.Flags;
204325d7b4fbSAlexey Lapshin   Ehdr.e_ehsize = sizeof(Elf_Ehdr);
204425d7b4fbSAlexey Lapshin   if (WriteSectionHeaders && Obj.sections().size() != 0) {
204525d7b4fbSAlexey Lapshin     Ehdr.e_shentsize = sizeof(Elf_Shdr);
204625d7b4fbSAlexey Lapshin     Ehdr.e_shoff = Obj.SHOff;
204725d7b4fbSAlexey Lapshin     // """
204825d7b4fbSAlexey Lapshin     // If the number of sections is greater than or equal to
204925d7b4fbSAlexey Lapshin     // SHN_LORESERVE (0xff00), this member has the value zero and the actual
205025d7b4fbSAlexey Lapshin     // number of section header table entries is contained in the sh_size field
205125d7b4fbSAlexey Lapshin     // of the section header at index 0.
205225d7b4fbSAlexey Lapshin     // """
205325d7b4fbSAlexey Lapshin     auto Shnum = Obj.sections().size() + 1;
205425d7b4fbSAlexey Lapshin     if (Shnum >= SHN_LORESERVE)
205525d7b4fbSAlexey Lapshin       Ehdr.e_shnum = 0;
205625d7b4fbSAlexey Lapshin     else
205725d7b4fbSAlexey Lapshin       Ehdr.e_shnum = Shnum;
205825d7b4fbSAlexey Lapshin     // """
205925d7b4fbSAlexey Lapshin     // If the section name string table section index is greater than or equal
206025d7b4fbSAlexey Lapshin     // to SHN_LORESERVE (0xff00), this member has the value SHN_XINDEX (0xffff)
206125d7b4fbSAlexey Lapshin     // and the actual index of the section name string table section is
206225d7b4fbSAlexey Lapshin     // contained in the sh_link field of the section header at index 0.
206325d7b4fbSAlexey Lapshin     // """
206425d7b4fbSAlexey Lapshin     if (Obj.SectionNames->Index >= SHN_LORESERVE)
206525d7b4fbSAlexey Lapshin       Ehdr.e_shstrndx = SHN_XINDEX;
206625d7b4fbSAlexey Lapshin     else
206725d7b4fbSAlexey Lapshin       Ehdr.e_shstrndx = Obj.SectionNames->Index;
206825d7b4fbSAlexey Lapshin   } else {
206925d7b4fbSAlexey Lapshin     Ehdr.e_shentsize = 0;
207025d7b4fbSAlexey Lapshin     Ehdr.e_shoff = 0;
207125d7b4fbSAlexey Lapshin     Ehdr.e_shnum = 0;
207225d7b4fbSAlexey Lapshin     Ehdr.e_shstrndx = 0;
207325d7b4fbSAlexey Lapshin   }
207425d7b4fbSAlexey Lapshin }
207525d7b4fbSAlexey Lapshin 
207625d7b4fbSAlexey Lapshin template <class ELFT> void ELFWriter<ELFT>::writePhdrs() {
207725d7b4fbSAlexey Lapshin   for (auto &Seg : Obj.segments())
207825d7b4fbSAlexey Lapshin     writePhdr(Seg);
207925d7b4fbSAlexey Lapshin }
208025d7b4fbSAlexey Lapshin 
208125d7b4fbSAlexey Lapshin template <class ELFT> void ELFWriter<ELFT>::writeShdrs() {
208225d7b4fbSAlexey Lapshin   // This reference serves to write the dummy section header at the begining
208325d7b4fbSAlexey Lapshin   // of the file. It is not used for anything else
208425d7b4fbSAlexey Lapshin   Elf_Shdr &Shdr =
208525d7b4fbSAlexey Lapshin       *reinterpret_cast<Elf_Shdr *>(Buf->getBufferStart() + Obj.SHOff);
208625d7b4fbSAlexey Lapshin   Shdr.sh_name = 0;
208725d7b4fbSAlexey Lapshin   Shdr.sh_type = SHT_NULL;
208825d7b4fbSAlexey Lapshin   Shdr.sh_flags = 0;
208925d7b4fbSAlexey Lapshin   Shdr.sh_addr = 0;
209025d7b4fbSAlexey Lapshin   Shdr.sh_offset = 0;
209125d7b4fbSAlexey Lapshin   // See writeEhdr for why we do this.
209225d7b4fbSAlexey Lapshin   uint64_t Shnum = Obj.sections().size() + 1;
209325d7b4fbSAlexey Lapshin   if (Shnum >= SHN_LORESERVE)
209425d7b4fbSAlexey Lapshin     Shdr.sh_size = Shnum;
209525d7b4fbSAlexey Lapshin   else
209625d7b4fbSAlexey Lapshin     Shdr.sh_size = 0;
209725d7b4fbSAlexey Lapshin   // See writeEhdr for why we do this.
209825d7b4fbSAlexey Lapshin   if (Obj.SectionNames != nullptr && Obj.SectionNames->Index >= SHN_LORESERVE)
209925d7b4fbSAlexey Lapshin     Shdr.sh_link = Obj.SectionNames->Index;
210025d7b4fbSAlexey Lapshin   else
210125d7b4fbSAlexey Lapshin     Shdr.sh_link = 0;
210225d7b4fbSAlexey Lapshin   Shdr.sh_info = 0;
210325d7b4fbSAlexey Lapshin   Shdr.sh_addralign = 0;
210425d7b4fbSAlexey Lapshin   Shdr.sh_entsize = 0;
210525d7b4fbSAlexey Lapshin 
210625d7b4fbSAlexey Lapshin   for (SectionBase &Sec : Obj.sections())
210725d7b4fbSAlexey Lapshin     writeShdr(Sec);
210825d7b4fbSAlexey Lapshin }
210925d7b4fbSAlexey Lapshin 
211025d7b4fbSAlexey Lapshin template <class ELFT> Error ELFWriter<ELFT>::writeSectionData() {
211125d7b4fbSAlexey Lapshin   for (SectionBase &Sec : Obj.sections())
211225d7b4fbSAlexey Lapshin     // Segments are responsible for writing their contents, so only write the
211325d7b4fbSAlexey Lapshin     // section data if the section is not in a segment. Note that this renders
211425d7b4fbSAlexey Lapshin     // sections in segments effectively immutable.
211525d7b4fbSAlexey Lapshin     if (Sec.ParentSegment == nullptr)
211625d7b4fbSAlexey Lapshin       if (Error Err = Sec.accept(*SecWriter))
211725d7b4fbSAlexey Lapshin         return Err;
211825d7b4fbSAlexey Lapshin 
211925d7b4fbSAlexey Lapshin   return Error::success();
212025d7b4fbSAlexey Lapshin }
212125d7b4fbSAlexey Lapshin 
212225d7b4fbSAlexey Lapshin template <class ELFT> void ELFWriter<ELFT>::writeSegmentData() {
212325d7b4fbSAlexey Lapshin   for (Segment &Seg : Obj.segments()) {
212425d7b4fbSAlexey Lapshin     size_t Size = std::min<size_t>(Seg.FileSize, Seg.getContents().size());
212525d7b4fbSAlexey Lapshin     std::memcpy(Buf->getBufferStart() + Seg.Offset, Seg.getContents().data(),
212625d7b4fbSAlexey Lapshin                 Size);
212725d7b4fbSAlexey Lapshin   }
212825d7b4fbSAlexey Lapshin 
212940dc8e68SGregory Alfonso   for (const auto &it : Obj.getUpdatedSections()) {
213025d7b4fbSAlexey Lapshin     SectionBase *Sec = it.first;
213125d7b4fbSAlexey Lapshin     ArrayRef<uint8_t> Data = it.second;
213225d7b4fbSAlexey Lapshin 
213325d7b4fbSAlexey Lapshin     auto *Parent = Sec->ParentSegment;
213425d7b4fbSAlexey Lapshin     assert(Parent && "This section should've been part of a segment.");
213525d7b4fbSAlexey Lapshin     uint64_t Offset =
213625d7b4fbSAlexey Lapshin         Sec->OriginalOffset - Parent->OriginalOffset + Parent->Offset;
213725d7b4fbSAlexey Lapshin     llvm::copy(Data, Buf->getBufferStart() + Offset);
213825d7b4fbSAlexey Lapshin   }
213925d7b4fbSAlexey Lapshin 
214025d7b4fbSAlexey Lapshin   // Iterate over removed sections and overwrite their old data with zeroes.
214125d7b4fbSAlexey Lapshin   for (auto &Sec : Obj.removedSections()) {
214225d7b4fbSAlexey Lapshin     Segment *Parent = Sec.ParentSegment;
214325d7b4fbSAlexey Lapshin     if (Parent == nullptr || Sec.Type == SHT_NOBITS || Sec.Size == 0)
214425d7b4fbSAlexey Lapshin       continue;
214525d7b4fbSAlexey Lapshin     uint64_t Offset =
214625d7b4fbSAlexey Lapshin         Sec.OriginalOffset - Parent->OriginalOffset + Parent->Offset;
214725d7b4fbSAlexey Lapshin     std::memset(Buf->getBufferStart() + Offset, 0, Sec.Size);
214825d7b4fbSAlexey Lapshin   }
214925d7b4fbSAlexey Lapshin }
215025d7b4fbSAlexey Lapshin 
215125d7b4fbSAlexey Lapshin template <class ELFT>
215225d7b4fbSAlexey Lapshin ELFWriter<ELFT>::ELFWriter(Object &Obj, raw_ostream &Buf, bool WSH,
215325d7b4fbSAlexey Lapshin                            bool OnlyKeepDebug)
215425d7b4fbSAlexey Lapshin     : Writer(Obj, Buf), WriteSectionHeaders(WSH && Obj.HadShdrs),
215525d7b4fbSAlexey Lapshin       OnlyKeepDebug(OnlyKeepDebug) {}
215625d7b4fbSAlexey Lapshin 
2157*10772807SIgor Kudrin Error Object::updateSectionData(SecPtr &Sec, ArrayRef<uint8_t> Data) {
2158*10772807SIgor Kudrin   if (!Sec->hasContents())
2159*10772807SIgor Kudrin     return createStringError(
2160*10772807SIgor Kudrin         errc::invalid_argument,
2161*10772807SIgor Kudrin         "section '%s' cannot be updated because it does not have contents",
2162*10772807SIgor Kudrin         Sec->Name.c_str());
2163*10772807SIgor Kudrin 
2164*10772807SIgor Kudrin   if (Data.size() > Sec->Size && Sec->ParentSegment)
2165*10772807SIgor Kudrin     return createStringError(errc::invalid_argument,
2166*10772807SIgor Kudrin                              "cannot fit data of size %zu into section '%s' "
2167*10772807SIgor Kudrin                              "with size %" PRIu64 " that is part of a segment",
2168*10772807SIgor Kudrin                              Data.size(), Sec->Name.c_str(), Sec->Size);
2169*10772807SIgor Kudrin 
2170*10772807SIgor Kudrin   if (!Sec->ParentSegment) {
2171*10772807SIgor Kudrin     Sec = std::make_unique<OwnedDataSection>(*Sec, Data);
2172*10772807SIgor Kudrin   } else {
2173*10772807SIgor Kudrin     // The segment writer will be in charge of updating these contents.
2174*10772807SIgor Kudrin     Sec->Size = Data.size();
2175*10772807SIgor Kudrin     UpdatedSections[Sec.get()] = Data;
2176*10772807SIgor Kudrin   }
2177*10772807SIgor Kudrin 
2178*10772807SIgor Kudrin   return Error::success();
2179*10772807SIgor Kudrin }
2180*10772807SIgor Kudrin 
218125d7b4fbSAlexey Lapshin Error Object::updateSection(StringRef Name, ArrayRef<uint8_t> Data) {
218225d7b4fbSAlexey Lapshin   auto It = llvm::find_if(Sections,
218325d7b4fbSAlexey Lapshin                           [&](const SecPtr &Sec) { return Sec->Name == Name; });
218425d7b4fbSAlexey Lapshin   if (It == Sections.end())
218525d7b4fbSAlexey Lapshin     return createStringError(errc::invalid_argument, "section '%s' not found",
218625d7b4fbSAlexey Lapshin                              Name.str().c_str());
2187*10772807SIgor Kudrin   return updateSectionData(*It, Data);
218825d7b4fbSAlexey Lapshin }
218925d7b4fbSAlexey Lapshin 
2190*10772807SIgor Kudrin Error Object::updateSectionData(SectionBase &S, ArrayRef<uint8_t> Data) {
2191*10772807SIgor Kudrin   auto It = llvm::find_if(Sections,
2192*10772807SIgor Kudrin                           [&](const SecPtr &Sec) { return Sec.get() == &S; });
2193*10772807SIgor Kudrin   assert(It != Sections.end() && "The section should belong to the object");
2194*10772807SIgor Kudrin   return updateSectionData(*It, Data);
219525d7b4fbSAlexey Lapshin }
219625d7b4fbSAlexey Lapshin 
219725d7b4fbSAlexey Lapshin Error Object::removeSections(
219825d7b4fbSAlexey Lapshin     bool AllowBrokenLinks, std::function<bool(const SectionBase &)> ToRemove) {
219925d7b4fbSAlexey Lapshin 
220025d7b4fbSAlexey Lapshin   auto Iter = std::stable_partition(
220125d7b4fbSAlexey Lapshin       std::begin(Sections), std::end(Sections), [=](const SecPtr &Sec) {
220225d7b4fbSAlexey Lapshin         if (ToRemove(*Sec))
220325d7b4fbSAlexey Lapshin           return false;
220407942987SFangrui Song         // TODO: A compressed relocation section may be recognized as
220507942987SFangrui Song         // RelocationSectionBase. We don't want such a section to be removed.
220607942987SFangrui Song         if (isa<CompressedSection>(Sec))
220707942987SFangrui Song           return true;
220825d7b4fbSAlexey Lapshin         if (auto RelSec = dyn_cast<RelocationSectionBase>(Sec.get())) {
220925d7b4fbSAlexey Lapshin           if (auto ToRelSec = RelSec->getSection())
221025d7b4fbSAlexey Lapshin             return !ToRemove(*ToRelSec);
221125d7b4fbSAlexey Lapshin         }
2212e142a556SPranav Kant         // Remove empty group sections.
2213e142a556SPranav Kant         if (Sec->Type == ELF::SHT_GROUP) {
2214e142a556SPranav Kant           auto GroupSec = cast<GroupSection>(Sec.get());
2215e142a556SPranav Kant           return !llvm::all_of(GroupSec->members(), ToRemove);
2216e142a556SPranav Kant         }
221725d7b4fbSAlexey Lapshin         return true;
221825d7b4fbSAlexey Lapshin       });
221925d7b4fbSAlexey Lapshin   if (SymbolTable != nullptr && ToRemove(*SymbolTable))
222025d7b4fbSAlexey Lapshin     SymbolTable = nullptr;
222125d7b4fbSAlexey Lapshin   if (SectionNames != nullptr && ToRemove(*SectionNames))
222225d7b4fbSAlexey Lapshin     SectionNames = nullptr;
222325d7b4fbSAlexey Lapshin   if (SectionIndexTable != nullptr && ToRemove(*SectionIndexTable))
222425d7b4fbSAlexey Lapshin     SectionIndexTable = nullptr;
222525d7b4fbSAlexey Lapshin   // Now make sure there are no remaining references to the sections that will
222625d7b4fbSAlexey Lapshin   // be removed. Sometimes it is impossible to remove a reference so we emit
222725d7b4fbSAlexey Lapshin   // an error here instead.
222825d7b4fbSAlexey Lapshin   std::unordered_set<const SectionBase *> RemoveSections;
222925d7b4fbSAlexey Lapshin   RemoveSections.reserve(std::distance(Iter, std::end(Sections)));
223025d7b4fbSAlexey Lapshin   for (auto &RemoveSec : make_range(Iter, std::end(Sections))) {
223125d7b4fbSAlexey Lapshin     for (auto &Segment : Segments)
223225d7b4fbSAlexey Lapshin       Segment->removeSection(RemoveSec.get());
223325d7b4fbSAlexey Lapshin     RemoveSec->onRemove();
223425d7b4fbSAlexey Lapshin     RemoveSections.insert(RemoveSec.get());
223525d7b4fbSAlexey Lapshin   }
223625d7b4fbSAlexey Lapshin 
223725d7b4fbSAlexey Lapshin   // For each section that remains alive, we want to remove the dead references.
223825d7b4fbSAlexey Lapshin   // This either might update the content of the section (e.g. remove symbols
223925d7b4fbSAlexey Lapshin   // from symbol table that belongs to removed section) or trigger an error if
224025d7b4fbSAlexey Lapshin   // a live section critically depends on a section being removed somehow
224125d7b4fbSAlexey Lapshin   // (e.g. the removed section is referenced by a relocation).
224225d7b4fbSAlexey Lapshin   for (auto &KeepSec : make_range(std::begin(Sections), Iter)) {
224325d7b4fbSAlexey Lapshin     if (Error E = KeepSec->removeSectionReferences(
224425d7b4fbSAlexey Lapshin             AllowBrokenLinks, [&RemoveSections](const SectionBase *Sec) {
224525d7b4fbSAlexey Lapshin               return RemoveSections.find(Sec) != RemoveSections.end();
224625d7b4fbSAlexey Lapshin             }))
224725d7b4fbSAlexey Lapshin       return E;
224825d7b4fbSAlexey Lapshin   }
224925d7b4fbSAlexey Lapshin 
225025d7b4fbSAlexey Lapshin   // Transfer removed sections into the Object RemovedSections container for use
225125d7b4fbSAlexey Lapshin   // later.
225225d7b4fbSAlexey Lapshin   std::move(Iter, Sections.end(), std::back_inserter(RemovedSections));
22532abe53a1SFangrui Song   // Now finally get rid of them all together.
225425d7b4fbSAlexey Lapshin   Sections.erase(Iter, std::end(Sections));
225525d7b4fbSAlexey Lapshin   return Error::success();
225625d7b4fbSAlexey Lapshin }
225725d7b4fbSAlexey Lapshin 
225825d7b4fbSAlexey Lapshin Error Object::replaceSections(
225925d7b4fbSAlexey Lapshin     const DenseMap<SectionBase *, SectionBase *> &FromTo) {
226025d7b4fbSAlexey Lapshin   auto SectionIndexLess = [](const SecPtr &Lhs, const SecPtr &Rhs) {
226125d7b4fbSAlexey Lapshin     return Lhs->Index < Rhs->Index;
226225d7b4fbSAlexey Lapshin   };
226325d7b4fbSAlexey Lapshin   assert(llvm::is_sorted(Sections, SectionIndexLess) &&
226425d7b4fbSAlexey Lapshin          "Sections are expected to be sorted by Index");
226525d7b4fbSAlexey Lapshin   // Set indices of new sections so that they can be later sorted into positions
226625d7b4fbSAlexey Lapshin   // of removed ones.
226725d7b4fbSAlexey Lapshin   for (auto &I : FromTo)
226825d7b4fbSAlexey Lapshin     I.second->Index = I.first->Index;
226925d7b4fbSAlexey Lapshin 
227025d7b4fbSAlexey Lapshin   // Notify all sections about the replacement.
227125d7b4fbSAlexey Lapshin   for (auto &Sec : Sections)
227225d7b4fbSAlexey Lapshin     Sec->replaceSectionReferences(FromTo);
227325d7b4fbSAlexey Lapshin 
227425d7b4fbSAlexey Lapshin   if (Error E = removeSections(
227525d7b4fbSAlexey Lapshin           /*AllowBrokenLinks=*/false,
227625d7b4fbSAlexey Lapshin           [=](const SectionBase &Sec) { return FromTo.count(&Sec) > 0; }))
227725d7b4fbSAlexey Lapshin     return E;
227825d7b4fbSAlexey Lapshin   llvm::sort(Sections, SectionIndexLess);
227925d7b4fbSAlexey Lapshin   return Error::success();
228025d7b4fbSAlexey Lapshin }
228125d7b4fbSAlexey Lapshin 
228225d7b4fbSAlexey Lapshin Error Object::removeSymbols(function_ref<bool(const Symbol &)> ToRemove) {
228325d7b4fbSAlexey Lapshin   if (SymbolTable)
228425d7b4fbSAlexey Lapshin     for (const SecPtr &Sec : Sections)
228525d7b4fbSAlexey Lapshin       if (Error E = Sec->removeSymbols(ToRemove))
228625d7b4fbSAlexey Lapshin         return E;
228725d7b4fbSAlexey Lapshin   return Error::success();
228825d7b4fbSAlexey Lapshin }
228925d7b4fbSAlexey Lapshin 
229025d7b4fbSAlexey Lapshin Error Object::addNewSymbolTable() {
229125d7b4fbSAlexey Lapshin   assert(!SymbolTable && "Object must not has a SymbolTable.");
229225d7b4fbSAlexey Lapshin 
229325d7b4fbSAlexey Lapshin   // Reuse an existing SHT_STRTAB section if it exists.
229425d7b4fbSAlexey Lapshin   StringTableSection *StrTab = nullptr;
229525d7b4fbSAlexey Lapshin   for (SectionBase &Sec : sections()) {
229625d7b4fbSAlexey Lapshin     if (Sec.Type == ELF::SHT_STRTAB && !(Sec.Flags & SHF_ALLOC)) {
229725d7b4fbSAlexey Lapshin       StrTab = static_cast<StringTableSection *>(&Sec);
229825d7b4fbSAlexey Lapshin 
229925d7b4fbSAlexey Lapshin       // Prefer a string table that is not the section header string table, if
230025d7b4fbSAlexey Lapshin       // such a table exists.
230125d7b4fbSAlexey Lapshin       if (SectionNames != &Sec)
230225d7b4fbSAlexey Lapshin         break;
230325d7b4fbSAlexey Lapshin     }
230425d7b4fbSAlexey Lapshin   }
230525d7b4fbSAlexey Lapshin   if (!StrTab)
230625d7b4fbSAlexey Lapshin     StrTab = &addSection<StringTableSection>();
230725d7b4fbSAlexey Lapshin 
230825d7b4fbSAlexey Lapshin   SymbolTableSection &SymTab = addSection<SymbolTableSection>();
230925d7b4fbSAlexey Lapshin   SymTab.Name = ".symtab";
231025d7b4fbSAlexey Lapshin   SymTab.Link = StrTab->Index;
231125d7b4fbSAlexey Lapshin   if (Error Err = SymTab.initialize(sections()))
231225d7b4fbSAlexey Lapshin     return Err;
231325d7b4fbSAlexey Lapshin   SymTab.addSymbol("", 0, 0, nullptr, 0, 0, 0, 0);
231425d7b4fbSAlexey Lapshin 
231525d7b4fbSAlexey Lapshin   SymbolTable = &SymTab;
231625d7b4fbSAlexey Lapshin 
231725d7b4fbSAlexey Lapshin   return Error::success();
231825d7b4fbSAlexey Lapshin }
231925d7b4fbSAlexey Lapshin 
232025d7b4fbSAlexey Lapshin // Orders segments such that if x = y->ParentSegment then y comes before x.
232125d7b4fbSAlexey Lapshin static void orderSegments(std::vector<Segment *> &Segments) {
232225d7b4fbSAlexey Lapshin   llvm::stable_sort(Segments, compareSegmentsByOffset);
232325d7b4fbSAlexey Lapshin }
232425d7b4fbSAlexey Lapshin 
232525d7b4fbSAlexey Lapshin // This function finds a consistent layout for a list of segments starting from
232625d7b4fbSAlexey Lapshin // an Offset. It assumes that Segments have been sorted by orderSegments and
232725d7b4fbSAlexey Lapshin // returns an Offset one past the end of the last segment.
232825d7b4fbSAlexey Lapshin static uint64_t layoutSegments(std::vector<Segment *> &Segments,
232925d7b4fbSAlexey Lapshin                                uint64_t Offset) {
233025d7b4fbSAlexey Lapshin   assert(llvm::is_sorted(Segments, compareSegmentsByOffset));
233125d7b4fbSAlexey Lapshin   // The only way a segment should move is if a section was between two
233225d7b4fbSAlexey Lapshin   // segments and that section was removed. If that section isn't in a segment
233325d7b4fbSAlexey Lapshin   // then it's acceptable, but not ideal, to simply move it to after the
233425d7b4fbSAlexey Lapshin   // segments. So we can simply layout segments one after the other accounting
233525d7b4fbSAlexey Lapshin   // for alignment.
233625d7b4fbSAlexey Lapshin   for (Segment *Seg : Segments) {
233725d7b4fbSAlexey Lapshin     // We assume that segments have been ordered by OriginalOffset and Index
233825d7b4fbSAlexey Lapshin     // such that a parent segment will always come before a child segment in
233925d7b4fbSAlexey Lapshin     // OrderedSegments. This means that the Offset of the ParentSegment should
234025d7b4fbSAlexey Lapshin     // already be set and we can set our offset relative to it.
234125d7b4fbSAlexey Lapshin     if (Seg->ParentSegment != nullptr) {
234225d7b4fbSAlexey Lapshin       Segment *Parent = Seg->ParentSegment;
234325d7b4fbSAlexey Lapshin       Seg->Offset =
234425d7b4fbSAlexey Lapshin           Parent->Offset + Seg->OriginalOffset - Parent->OriginalOffset;
234525d7b4fbSAlexey Lapshin     } else {
234625d7b4fbSAlexey Lapshin       Seg->Offset =
234725d7b4fbSAlexey Lapshin           alignTo(Offset, std::max<uint64_t>(Seg->Align, 1), Seg->VAddr);
234825d7b4fbSAlexey Lapshin     }
234925d7b4fbSAlexey Lapshin     Offset = std::max(Offset, Seg->Offset + Seg->FileSize);
235025d7b4fbSAlexey Lapshin   }
235125d7b4fbSAlexey Lapshin   return Offset;
235225d7b4fbSAlexey Lapshin }
235325d7b4fbSAlexey Lapshin 
235425d7b4fbSAlexey Lapshin // This function finds a consistent layout for a list of sections. It assumes
235525d7b4fbSAlexey Lapshin // that the ->ParentSegment of each section has already been laid out. The
235625d7b4fbSAlexey Lapshin // supplied starting Offset is used for the starting offset of any section that
235725d7b4fbSAlexey Lapshin // does not have a ParentSegment. It returns either the offset given if all
235825d7b4fbSAlexey Lapshin // sections had a ParentSegment or an offset one past the last section if there
235925d7b4fbSAlexey Lapshin // was a section that didn't have a ParentSegment.
236025d7b4fbSAlexey Lapshin template <class Range>
236125d7b4fbSAlexey Lapshin static uint64_t layoutSections(Range Sections, uint64_t Offset) {
236225d7b4fbSAlexey Lapshin   // Now the offset of every segment has been set we can assign the offsets
236325d7b4fbSAlexey Lapshin   // of each section. For sections that are covered by a segment we should use
236425d7b4fbSAlexey Lapshin   // the segment's original offset and the section's original offset to compute
236525d7b4fbSAlexey Lapshin   // the offset from the start of the segment. Using the offset from the start
236625d7b4fbSAlexey Lapshin   // of the segment we can assign a new offset to the section. For sections not
236725d7b4fbSAlexey Lapshin   // covered by segments we can just bump Offset to the next valid location.
236825d7b4fbSAlexey Lapshin   // While it is not necessary, layout the sections in the order based on their
236925d7b4fbSAlexey Lapshin   // original offsets to resemble the input file as close as possible.
237025d7b4fbSAlexey Lapshin   std::vector<SectionBase *> OutOfSegmentSections;
237125d7b4fbSAlexey Lapshin   uint32_t Index = 1;
237225d7b4fbSAlexey Lapshin   for (auto &Sec : Sections) {
237325d7b4fbSAlexey Lapshin     Sec.Index = Index++;
237425d7b4fbSAlexey Lapshin     if (Sec.ParentSegment != nullptr) {
2375f3df0cf3SDavid Blaikie       const Segment &Segment = *Sec.ParentSegment;
237625d7b4fbSAlexey Lapshin       Sec.Offset =
237725d7b4fbSAlexey Lapshin           Segment.Offset + (Sec.OriginalOffset - Segment.OriginalOffset);
237825d7b4fbSAlexey Lapshin     } else
237925d7b4fbSAlexey Lapshin       OutOfSegmentSections.push_back(&Sec);
238025d7b4fbSAlexey Lapshin   }
238125d7b4fbSAlexey Lapshin 
238225d7b4fbSAlexey Lapshin   llvm::stable_sort(OutOfSegmentSections,
238325d7b4fbSAlexey Lapshin                     [](const SectionBase *Lhs, const SectionBase *Rhs) {
238425d7b4fbSAlexey Lapshin                       return Lhs->OriginalOffset < Rhs->OriginalOffset;
238525d7b4fbSAlexey Lapshin                     });
238625d7b4fbSAlexey Lapshin   for (auto *Sec : OutOfSegmentSections) {
238725d7b4fbSAlexey Lapshin     Offset = alignTo(Offset, Sec->Align == 0 ? 1 : Sec->Align);
238825d7b4fbSAlexey Lapshin     Sec->Offset = Offset;
238925d7b4fbSAlexey Lapshin     if (Sec->Type != SHT_NOBITS)
239025d7b4fbSAlexey Lapshin       Offset += Sec->Size;
239125d7b4fbSAlexey Lapshin   }
239225d7b4fbSAlexey Lapshin   return Offset;
239325d7b4fbSAlexey Lapshin }
239425d7b4fbSAlexey Lapshin 
239525d7b4fbSAlexey Lapshin // Rewrite sh_offset after some sections are changed to SHT_NOBITS and thus
239625d7b4fbSAlexey Lapshin // occupy no space in the file.
239725d7b4fbSAlexey Lapshin static uint64_t layoutSectionsForOnlyKeepDebug(Object &Obj, uint64_t Off) {
239825d7b4fbSAlexey Lapshin   // The layout algorithm requires the sections to be handled in the order of
239925d7b4fbSAlexey Lapshin   // their offsets in the input file, at least inside segments.
240025d7b4fbSAlexey Lapshin   std::vector<SectionBase *> Sections;
240125d7b4fbSAlexey Lapshin   Sections.reserve(Obj.sections().size());
240225d7b4fbSAlexey Lapshin   uint32_t Index = 1;
240325d7b4fbSAlexey Lapshin   for (auto &Sec : Obj.sections()) {
240425d7b4fbSAlexey Lapshin     Sec.Index = Index++;
240525d7b4fbSAlexey Lapshin     Sections.push_back(&Sec);
240625d7b4fbSAlexey Lapshin   }
240725d7b4fbSAlexey Lapshin   llvm::stable_sort(Sections,
240825d7b4fbSAlexey Lapshin                     [](const SectionBase *Lhs, const SectionBase *Rhs) {
240925d7b4fbSAlexey Lapshin                       return Lhs->OriginalOffset < Rhs->OriginalOffset;
241025d7b4fbSAlexey Lapshin                     });
241125d7b4fbSAlexey Lapshin 
241225d7b4fbSAlexey Lapshin   for (auto *Sec : Sections) {
241325d7b4fbSAlexey Lapshin     auto *FirstSec = Sec->ParentSegment && Sec->ParentSegment->Type == PT_LOAD
241425d7b4fbSAlexey Lapshin                          ? Sec->ParentSegment->firstSection()
241525d7b4fbSAlexey Lapshin                          : nullptr;
241625d7b4fbSAlexey Lapshin 
241725d7b4fbSAlexey Lapshin     // The first section in a PT_LOAD has to have congruent offset and address
241825d7b4fbSAlexey Lapshin     // modulo the alignment, which usually equals the maximum page size.
241925d7b4fbSAlexey Lapshin     if (FirstSec && FirstSec == Sec)
242025d7b4fbSAlexey Lapshin       Off = alignTo(Off, Sec->ParentSegment->Align, Sec->Addr);
242125d7b4fbSAlexey Lapshin 
242225d7b4fbSAlexey Lapshin     // sh_offset is not significant for SHT_NOBITS sections, but the congruence
242325d7b4fbSAlexey Lapshin     // rule must be followed if it is the first section in a PT_LOAD. Do not
242425d7b4fbSAlexey Lapshin     // advance Off.
242525d7b4fbSAlexey Lapshin     if (Sec->Type == SHT_NOBITS) {
242625d7b4fbSAlexey Lapshin       Sec->Offset = Off;
242725d7b4fbSAlexey Lapshin       continue;
242825d7b4fbSAlexey Lapshin     }
242925d7b4fbSAlexey Lapshin 
243025d7b4fbSAlexey Lapshin     if (!FirstSec) {
243125d7b4fbSAlexey Lapshin       // FirstSec being nullptr generally means that Sec does not have the
243225d7b4fbSAlexey Lapshin       // SHF_ALLOC flag.
243325d7b4fbSAlexey Lapshin       Off = Sec->Align ? alignTo(Off, Sec->Align) : Off;
243425d7b4fbSAlexey Lapshin     } else if (FirstSec != Sec) {
243525d7b4fbSAlexey Lapshin       // The offset is relative to the first section in the PT_LOAD segment. Use
243625d7b4fbSAlexey Lapshin       // sh_offset for non-SHF_ALLOC sections.
243725d7b4fbSAlexey Lapshin       Off = Sec->OriginalOffset - FirstSec->OriginalOffset + FirstSec->Offset;
243825d7b4fbSAlexey Lapshin     }
243925d7b4fbSAlexey Lapshin     Sec->Offset = Off;
244025d7b4fbSAlexey Lapshin     Off += Sec->Size;
244125d7b4fbSAlexey Lapshin   }
244225d7b4fbSAlexey Lapshin   return Off;
244325d7b4fbSAlexey Lapshin }
244425d7b4fbSAlexey Lapshin 
244525d7b4fbSAlexey Lapshin // Rewrite p_offset and p_filesz of non-PT_PHDR segments after sh_offset values
244625d7b4fbSAlexey Lapshin // have been updated.
244725d7b4fbSAlexey Lapshin static uint64_t layoutSegmentsForOnlyKeepDebug(std::vector<Segment *> &Segments,
244825d7b4fbSAlexey Lapshin                                                uint64_t HdrEnd) {
244925d7b4fbSAlexey Lapshin   uint64_t MaxOffset = 0;
245025d7b4fbSAlexey Lapshin   for (Segment *Seg : Segments) {
245125d7b4fbSAlexey Lapshin     if (Seg->Type == PT_PHDR)
245225d7b4fbSAlexey Lapshin       continue;
245325d7b4fbSAlexey Lapshin 
245425d7b4fbSAlexey Lapshin     // The segment offset is generally the offset of the first section.
245525d7b4fbSAlexey Lapshin     //
245625d7b4fbSAlexey Lapshin     // For a segment containing no section (see sectionWithinSegment), if it has
245725d7b4fbSAlexey Lapshin     // a parent segment, copy the parent segment's offset field. This works for
245825d7b4fbSAlexey Lapshin     // empty PT_TLS. If no parent segment, use 0: the segment is not useful for
245925d7b4fbSAlexey Lapshin     // debugging anyway.
246025d7b4fbSAlexey Lapshin     const SectionBase *FirstSec = Seg->firstSection();
246125d7b4fbSAlexey Lapshin     uint64_t Offset =
246225d7b4fbSAlexey Lapshin         FirstSec ? FirstSec->Offset
246325d7b4fbSAlexey Lapshin                  : (Seg->ParentSegment ? Seg->ParentSegment->Offset : 0);
246425d7b4fbSAlexey Lapshin     uint64_t FileSize = 0;
246525d7b4fbSAlexey Lapshin     for (const SectionBase *Sec : Seg->Sections) {
246625d7b4fbSAlexey Lapshin       uint64_t Size = Sec->Type == SHT_NOBITS ? 0 : Sec->Size;
246725d7b4fbSAlexey Lapshin       if (Sec->Offset + Size > Offset)
246825d7b4fbSAlexey Lapshin         FileSize = std::max(FileSize, Sec->Offset + Size - Offset);
246925d7b4fbSAlexey Lapshin     }
247025d7b4fbSAlexey Lapshin 
247125d7b4fbSAlexey Lapshin     // If the segment includes EHDR and program headers, don't make it smaller
247225d7b4fbSAlexey Lapshin     // than the headers.
247325d7b4fbSAlexey Lapshin     if (Seg->Offset < HdrEnd && HdrEnd <= Seg->Offset + Seg->FileSize) {
247425d7b4fbSAlexey Lapshin       FileSize += Offset - Seg->Offset;
247525d7b4fbSAlexey Lapshin       Offset = Seg->Offset;
247625d7b4fbSAlexey Lapshin       FileSize = std::max(FileSize, HdrEnd - Offset);
247725d7b4fbSAlexey Lapshin     }
247825d7b4fbSAlexey Lapshin 
247925d7b4fbSAlexey Lapshin     Seg->Offset = Offset;
248025d7b4fbSAlexey Lapshin     Seg->FileSize = FileSize;
248125d7b4fbSAlexey Lapshin     MaxOffset = std::max(MaxOffset, Offset + FileSize);
248225d7b4fbSAlexey Lapshin   }
248325d7b4fbSAlexey Lapshin   return MaxOffset;
248425d7b4fbSAlexey Lapshin }
248525d7b4fbSAlexey Lapshin 
248625d7b4fbSAlexey Lapshin template <class ELFT> void ELFWriter<ELFT>::initEhdrSegment() {
248725d7b4fbSAlexey Lapshin   Segment &ElfHdr = Obj.ElfHdrSegment;
248825d7b4fbSAlexey Lapshin   ElfHdr.Type = PT_PHDR;
248925d7b4fbSAlexey Lapshin   ElfHdr.Flags = 0;
249025d7b4fbSAlexey Lapshin   ElfHdr.VAddr = 0;
249125d7b4fbSAlexey Lapshin   ElfHdr.PAddr = 0;
249225d7b4fbSAlexey Lapshin   ElfHdr.FileSize = ElfHdr.MemSize = sizeof(Elf_Ehdr);
249325d7b4fbSAlexey Lapshin   ElfHdr.Align = 0;
249425d7b4fbSAlexey Lapshin }
249525d7b4fbSAlexey Lapshin 
249625d7b4fbSAlexey Lapshin template <class ELFT> void ELFWriter<ELFT>::assignOffsets() {
249725d7b4fbSAlexey Lapshin   // We need a temporary list of segments that has a special order to it
249825d7b4fbSAlexey Lapshin   // so that we know that anytime ->ParentSegment is set that segment has
249925d7b4fbSAlexey Lapshin   // already had its offset properly set.
250025d7b4fbSAlexey Lapshin   std::vector<Segment *> OrderedSegments;
250125d7b4fbSAlexey Lapshin   for (Segment &Segment : Obj.segments())
250225d7b4fbSAlexey Lapshin     OrderedSegments.push_back(&Segment);
250325d7b4fbSAlexey Lapshin   OrderedSegments.push_back(&Obj.ElfHdrSegment);
250425d7b4fbSAlexey Lapshin   OrderedSegments.push_back(&Obj.ProgramHdrSegment);
250525d7b4fbSAlexey Lapshin   orderSegments(OrderedSegments);
250625d7b4fbSAlexey Lapshin 
250725d7b4fbSAlexey Lapshin   uint64_t Offset;
250825d7b4fbSAlexey Lapshin   if (OnlyKeepDebug) {
250925d7b4fbSAlexey Lapshin     // For --only-keep-debug, the sections that did not preserve contents were
251025d7b4fbSAlexey Lapshin     // changed to SHT_NOBITS. We now rewrite sh_offset fields of sections, and
251125d7b4fbSAlexey Lapshin     // then rewrite p_offset/p_filesz of program headers.
251225d7b4fbSAlexey Lapshin     uint64_t HdrEnd =
251325d7b4fbSAlexey Lapshin         sizeof(Elf_Ehdr) + llvm::size(Obj.segments()) * sizeof(Elf_Phdr);
251425d7b4fbSAlexey Lapshin     Offset = layoutSectionsForOnlyKeepDebug(Obj, HdrEnd);
251525d7b4fbSAlexey Lapshin     Offset = std::max(Offset,
251625d7b4fbSAlexey Lapshin                       layoutSegmentsForOnlyKeepDebug(OrderedSegments, HdrEnd));
251725d7b4fbSAlexey Lapshin   } else {
251825d7b4fbSAlexey Lapshin     // Offset is used as the start offset of the first segment to be laid out.
251925d7b4fbSAlexey Lapshin     // Since the ELF Header (ElfHdrSegment) must be at the start of the file,
252025d7b4fbSAlexey Lapshin     // we start at offset 0.
252125d7b4fbSAlexey Lapshin     Offset = layoutSegments(OrderedSegments, 0);
252225d7b4fbSAlexey Lapshin     Offset = layoutSections(Obj.sections(), Offset);
252325d7b4fbSAlexey Lapshin   }
252425d7b4fbSAlexey Lapshin   // If we need to write the section header table out then we need to align the
252525d7b4fbSAlexey Lapshin   // Offset so that SHOffset is valid.
252625d7b4fbSAlexey Lapshin   if (WriteSectionHeaders)
252725d7b4fbSAlexey Lapshin     Offset = alignTo(Offset, sizeof(Elf_Addr));
252825d7b4fbSAlexey Lapshin   Obj.SHOff = Offset;
252925d7b4fbSAlexey Lapshin }
253025d7b4fbSAlexey Lapshin 
253125d7b4fbSAlexey Lapshin template <class ELFT> size_t ELFWriter<ELFT>::totalSize() const {
253225d7b4fbSAlexey Lapshin   // We already have the section header offset so we can calculate the total
253325d7b4fbSAlexey Lapshin   // size by just adding up the size of each section header.
253425d7b4fbSAlexey Lapshin   if (!WriteSectionHeaders)
253525d7b4fbSAlexey Lapshin     return Obj.SHOff;
253625d7b4fbSAlexey Lapshin   size_t ShdrCount = Obj.sections().size() + 1; // Includes null shdr.
253725d7b4fbSAlexey Lapshin   return Obj.SHOff + ShdrCount * sizeof(Elf_Shdr);
253825d7b4fbSAlexey Lapshin }
253925d7b4fbSAlexey Lapshin 
254025d7b4fbSAlexey Lapshin template <class ELFT> Error ELFWriter<ELFT>::write() {
254125d7b4fbSAlexey Lapshin   // Segment data must be written first, so that the ELF header and program
254225d7b4fbSAlexey Lapshin   // header tables can overwrite it, if covered by a segment.
254325d7b4fbSAlexey Lapshin   writeSegmentData();
254425d7b4fbSAlexey Lapshin   writeEhdr();
254525d7b4fbSAlexey Lapshin   writePhdrs();
254625d7b4fbSAlexey Lapshin   if (Error E = writeSectionData())
254725d7b4fbSAlexey Lapshin     return E;
254825d7b4fbSAlexey Lapshin   if (WriteSectionHeaders)
254925d7b4fbSAlexey Lapshin     writeShdrs();
255025d7b4fbSAlexey Lapshin 
255125d7b4fbSAlexey Lapshin   // TODO: Implement direct writing to the output stream (without intermediate
255225d7b4fbSAlexey Lapshin   // memory buffer Buf).
255325d7b4fbSAlexey Lapshin   Out.write(Buf->getBufferStart(), Buf->getBufferSize());
255425d7b4fbSAlexey Lapshin   return Error::success();
255525d7b4fbSAlexey Lapshin }
255625d7b4fbSAlexey Lapshin 
255725d7b4fbSAlexey Lapshin static Error removeUnneededSections(Object &Obj) {
255825d7b4fbSAlexey Lapshin   // We can remove an empty symbol table from non-relocatable objects.
255925d7b4fbSAlexey Lapshin   // Relocatable objects typically have relocation sections whose
256025d7b4fbSAlexey Lapshin   // sh_link field points to .symtab, so we can't remove .symtab
256125d7b4fbSAlexey Lapshin   // even if it is empty.
256225d7b4fbSAlexey Lapshin   if (Obj.isRelocatable() || Obj.SymbolTable == nullptr ||
256325d7b4fbSAlexey Lapshin       !Obj.SymbolTable->empty())
256425d7b4fbSAlexey Lapshin     return Error::success();
256525d7b4fbSAlexey Lapshin 
256625d7b4fbSAlexey Lapshin   // .strtab can be used for section names. In such a case we shouldn't
256725d7b4fbSAlexey Lapshin   // remove it.
256825d7b4fbSAlexey Lapshin   auto *StrTab = Obj.SymbolTable->getStrTab() == Obj.SectionNames
256925d7b4fbSAlexey Lapshin                      ? nullptr
257025d7b4fbSAlexey Lapshin                      : Obj.SymbolTable->getStrTab();
257125d7b4fbSAlexey Lapshin   return Obj.removeSections(false, [&](const SectionBase &Sec) {
257225d7b4fbSAlexey Lapshin     return &Sec == Obj.SymbolTable || &Sec == StrTab;
257325d7b4fbSAlexey Lapshin   });
257425d7b4fbSAlexey Lapshin }
257525d7b4fbSAlexey Lapshin 
257625d7b4fbSAlexey Lapshin template <class ELFT> Error ELFWriter<ELFT>::finalize() {
257725d7b4fbSAlexey Lapshin   // It could happen that SectionNames has been removed and yet the user wants
257825d7b4fbSAlexey Lapshin   // a section header table output. We need to throw an error if a user tries
257925d7b4fbSAlexey Lapshin   // to do that.
258025d7b4fbSAlexey Lapshin   if (Obj.SectionNames == nullptr && WriteSectionHeaders)
258125d7b4fbSAlexey Lapshin     return createStringError(llvm::errc::invalid_argument,
258225d7b4fbSAlexey Lapshin                              "cannot write section header table because "
258325d7b4fbSAlexey Lapshin                              "section header string table was removed");
258425d7b4fbSAlexey Lapshin 
258525d7b4fbSAlexey Lapshin   if (Error E = removeUnneededSections(Obj))
258625d7b4fbSAlexey Lapshin     return E;
258725d7b4fbSAlexey Lapshin 
2588744e589cSAndrew Ng   // If the .symtab indices have not been changed, restore the sh_link to
2589744e589cSAndrew Ng   // .symtab for sections that were linked to .symtab.
2590744e589cSAndrew Ng   if (Obj.SymbolTable && !Obj.SymbolTable->indicesChanged())
2591744e589cSAndrew Ng     for (SectionBase &Sec : Obj.sections())
2592744e589cSAndrew Ng       Sec.restoreSymTabLink(*Obj.SymbolTable);
2593744e589cSAndrew Ng 
259425d7b4fbSAlexey Lapshin   // We need to assign indexes before we perform layout because we need to know
259525d7b4fbSAlexey Lapshin   // if we need large indexes or not. We can assign indexes first and check as
259625d7b4fbSAlexey Lapshin   // we go to see if we will actully need large indexes.
259725d7b4fbSAlexey Lapshin   bool NeedsLargeIndexes = false;
259825d7b4fbSAlexey Lapshin   if (Obj.sections().size() >= SHN_LORESERVE) {
259925d7b4fbSAlexey Lapshin     SectionTableRef Sections = Obj.sections();
260025d7b4fbSAlexey Lapshin     // Sections doesn't include the null section header, so account for this
260125d7b4fbSAlexey Lapshin     // when skipping the first N sections.
260225d7b4fbSAlexey Lapshin     NeedsLargeIndexes =
260325d7b4fbSAlexey Lapshin         any_of(drop_begin(Sections, SHN_LORESERVE - 1),
260425d7b4fbSAlexey Lapshin                [](const SectionBase &Sec) { return Sec.HasSymbol; });
260525d7b4fbSAlexey Lapshin     // TODO: handle case where only one section needs the large index table but
260625d7b4fbSAlexey Lapshin     // only needs it because the large index table hasn't been removed yet.
260725d7b4fbSAlexey Lapshin   }
260825d7b4fbSAlexey Lapshin 
260925d7b4fbSAlexey Lapshin   if (NeedsLargeIndexes) {
261025d7b4fbSAlexey Lapshin     // This means we definitely need to have a section index table but if we
261125d7b4fbSAlexey Lapshin     // already have one then we should use it instead of making a new one.
261225d7b4fbSAlexey Lapshin     if (Obj.SymbolTable != nullptr && Obj.SectionIndexTable == nullptr) {
261325d7b4fbSAlexey Lapshin       // Addition of a section to the end does not invalidate the indexes of
261425d7b4fbSAlexey Lapshin       // other sections and assigns the correct index to the new section.
261525d7b4fbSAlexey Lapshin       auto &Shndx = Obj.addSection<SectionIndexSection>();
261625d7b4fbSAlexey Lapshin       Obj.SymbolTable->setShndxTable(&Shndx);
261725d7b4fbSAlexey Lapshin       Shndx.setSymTab(Obj.SymbolTable);
261825d7b4fbSAlexey Lapshin     }
261925d7b4fbSAlexey Lapshin   } else {
262025d7b4fbSAlexey Lapshin     // Since we don't need SectionIndexTable we should remove it and all
262125d7b4fbSAlexey Lapshin     // references to it.
262225d7b4fbSAlexey Lapshin     if (Obj.SectionIndexTable != nullptr) {
262325d7b4fbSAlexey Lapshin       // We do not support sections referring to the section index table.
262425d7b4fbSAlexey Lapshin       if (Error E = Obj.removeSections(false /*AllowBrokenLinks*/,
262525d7b4fbSAlexey Lapshin                                        [this](const SectionBase &Sec) {
262625d7b4fbSAlexey Lapshin                                          return &Sec == Obj.SectionIndexTable;
262725d7b4fbSAlexey Lapshin                                        }))
262825d7b4fbSAlexey Lapshin         return E;
262925d7b4fbSAlexey Lapshin     }
263025d7b4fbSAlexey Lapshin   }
263125d7b4fbSAlexey Lapshin 
263225d7b4fbSAlexey Lapshin   // Make sure we add the names of all the sections. Importantly this must be
263325d7b4fbSAlexey Lapshin   // done after we decide to add or remove SectionIndexes.
263425d7b4fbSAlexey Lapshin   if (Obj.SectionNames != nullptr)
263525d7b4fbSAlexey Lapshin     for (const SectionBase &Sec : Obj.sections())
263625d7b4fbSAlexey Lapshin       Obj.SectionNames->addString(Sec.Name);
263725d7b4fbSAlexey Lapshin 
263825d7b4fbSAlexey Lapshin   initEhdrSegment();
263925d7b4fbSAlexey Lapshin 
264025d7b4fbSAlexey Lapshin   // Before we can prepare for layout the indexes need to be finalized.
264125d7b4fbSAlexey Lapshin   // Also, the output arch may not be the same as the input arch, so fix up
264225d7b4fbSAlexey Lapshin   // size-related fields before doing layout calculations.
264325d7b4fbSAlexey Lapshin   uint64_t Index = 0;
264425d7b4fbSAlexey Lapshin   auto SecSizer = std::make_unique<ELFSectionSizer<ELFT>>();
264525d7b4fbSAlexey Lapshin   for (SectionBase &Sec : Obj.sections()) {
264625d7b4fbSAlexey Lapshin     Sec.Index = Index++;
264725d7b4fbSAlexey Lapshin     if (Error Err = Sec.accept(*SecSizer))
264825d7b4fbSAlexey Lapshin       return Err;
264925d7b4fbSAlexey Lapshin   }
265025d7b4fbSAlexey Lapshin 
265125d7b4fbSAlexey Lapshin   // The symbol table does not update all other sections on update. For
265225d7b4fbSAlexey Lapshin   // instance, symbol names are not added as new symbols are added. This means
265325d7b4fbSAlexey Lapshin   // that some sections, like .strtab, don't yet have their final size.
265425d7b4fbSAlexey Lapshin   if (Obj.SymbolTable != nullptr)
265525d7b4fbSAlexey Lapshin     Obj.SymbolTable->prepareForLayout();
265625d7b4fbSAlexey Lapshin 
265725d7b4fbSAlexey Lapshin   // Now that all strings are added we want to finalize string table builders,
265825d7b4fbSAlexey Lapshin   // because that affects section sizes which in turn affects section offsets.
265925d7b4fbSAlexey Lapshin   for (SectionBase &Sec : Obj.sections())
266025d7b4fbSAlexey Lapshin     if (auto StrTab = dyn_cast<StringTableSection>(&Sec))
266125d7b4fbSAlexey Lapshin       StrTab->prepareForLayout();
266225d7b4fbSAlexey Lapshin 
266325d7b4fbSAlexey Lapshin   assignOffsets();
266425d7b4fbSAlexey Lapshin 
266525d7b4fbSAlexey Lapshin   // layoutSections could have modified section indexes, so we need
266625d7b4fbSAlexey Lapshin   // to fill the index table after assignOffsets.
266725d7b4fbSAlexey Lapshin   if (Obj.SymbolTable != nullptr)
266825d7b4fbSAlexey Lapshin     Obj.SymbolTable->fillShndxTable();
266925d7b4fbSAlexey Lapshin 
267025d7b4fbSAlexey Lapshin   // Finally now that all offsets and indexes have been set we can finalize any
267125d7b4fbSAlexey Lapshin   // remaining issues.
267225d7b4fbSAlexey Lapshin   uint64_t Offset = Obj.SHOff + sizeof(Elf_Shdr);
267325d7b4fbSAlexey Lapshin   for (SectionBase &Sec : Obj.sections()) {
267425d7b4fbSAlexey Lapshin     Sec.HeaderOffset = Offset;
267525d7b4fbSAlexey Lapshin     Offset += sizeof(Elf_Shdr);
267625d7b4fbSAlexey Lapshin     if (WriteSectionHeaders)
267725d7b4fbSAlexey Lapshin       Sec.NameIndex = Obj.SectionNames->findIndex(Sec.Name);
267825d7b4fbSAlexey Lapshin     Sec.finalize();
267925d7b4fbSAlexey Lapshin   }
268025d7b4fbSAlexey Lapshin 
268125d7b4fbSAlexey Lapshin   size_t TotalSize = totalSize();
268225d7b4fbSAlexey Lapshin   Buf = WritableMemoryBuffer::getNewMemBuffer(TotalSize);
268325d7b4fbSAlexey Lapshin   if (!Buf)
268425d7b4fbSAlexey Lapshin     return createStringError(errc::not_enough_memory,
268525d7b4fbSAlexey Lapshin                              "failed to allocate memory buffer of " +
268625d7b4fbSAlexey Lapshin                                  Twine::utohexstr(TotalSize) + " bytes");
268725d7b4fbSAlexey Lapshin 
268825d7b4fbSAlexey Lapshin   SecWriter = std::make_unique<ELFSectionWriter<ELFT>>(*Buf);
268925d7b4fbSAlexey Lapshin   return Error::success();
269025d7b4fbSAlexey Lapshin }
269125d7b4fbSAlexey Lapshin 
269225d7b4fbSAlexey Lapshin Error BinaryWriter::write() {
26934070dffdSquic-akaryaki   SmallVector<const SectionBase *, 30> SectionsToWrite;
26944070dffdSquic-akaryaki   for (const SectionBase &Sec : Obj.allocSections()) {
2695535520c6Squic-akaryaki     if (Sec.Type != SHT_NOBITS && Sec.Size > 0)
26964070dffdSquic-akaryaki       SectionsToWrite.push_back(&Sec);
26974070dffdSquic-akaryaki   }
26984070dffdSquic-akaryaki 
26994070dffdSquic-akaryaki   if (SectionsToWrite.empty())
27004070dffdSquic-akaryaki     return Error::success();
27014070dffdSquic-akaryaki 
27024070dffdSquic-akaryaki   llvm::stable_sort(SectionsToWrite,
27034070dffdSquic-akaryaki                     [](const SectionBase *LHS, const SectionBase *RHS) {
27044070dffdSquic-akaryaki                       return LHS->Offset < RHS->Offset;
27054070dffdSquic-akaryaki                     });
27064070dffdSquic-akaryaki 
27074070dffdSquic-akaryaki   assert(SectionsToWrite.front()->Offset == 0);
27084070dffdSquic-akaryaki 
27094070dffdSquic-akaryaki   for (size_t i = 0; i != SectionsToWrite.size(); ++i) {
27104070dffdSquic-akaryaki     const SectionBase &Sec = *SectionsToWrite[i];
271125d7b4fbSAlexey Lapshin     if (Error Err = Sec.accept(*SecWriter))
271225d7b4fbSAlexey Lapshin       return Err;
27134070dffdSquic-akaryaki     if (GapFill == 0)
27144070dffdSquic-akaryaki       continue;
27154070dffdSquic-akaryaki     uint64_t PadOffset = (i < SectionsToWrite.size() - 1)
27164070dffdSquic-akaryaki                              ? SectionsToWrite[i + 1]->Offset
27174070dffdSquic-akaryaki                              : Buf->getBufferSize();
27184070dffdSquic-akaryaki     assert(PadOffset <= Buf->getBufferSize());
27194070dffdSquic-akaryaki     assert(Sec.Offset + Sec.Size <= PadOffset);
27204070dffdSquic-akaryaki     std::fill(Buf->getBufferStart() + Sec.Offset + Sec.Size,
27214070dffdSquic-akaryaki               Buf->getBufferStart() + PadOffset, GapFill);
27224070dffdSquic-akaryaki   }
272325d7b4fbSAlexey Lapshin 
272425d7b4fbSAlexey Lapshin   // TODO: Implement direct writing to the output stream (without intermediate
272525d7b4fbSAlexey Lapshin   // memory buffer Buf).
272625d7b4fbSAlexey Lapshin   Out.write(Buf->getBufferStart(), Buf->getBufferSize());
272725d7b4fbSAlexey Lapshin   return Error::success();
272825d7b4fbSAlexey Lapshin }
272925d7b4fbSAlexey Lapshin 
273025d7b4fbSAlexey Lapshin Error BinaryWriter::finalize() {
273125d7b4fbSAlexey Lapshin   // Compute the section LMA based on its sh_offset and the containing segment's
273225d7b4fbSAlexey Lapshin   // p_offset and p_paddr. Also compute the minimum LMA of all non-empty
273325d7b4fbSAlexey Lapshin   // sections as MinAddr. In the output, the contents between address 0 and
273425d7b4fbSAlexey Lapshin   // MinAddr will be skipped.
273525d7b4fbSAlexey Lapshin   uint64_t MinAddr = UINT64_MAX;
273625d7b4fbSAlexey Lapshin   for (SectionBase &Sec : Obj.allocSections()) {
273725d7b4fbSAlexey Lapshin     if (Sec.ParentSegment != nullptr)
2738c973123fSAlexey Karyakin       Sec.Addr =
2739c973123fSAlexey Karyakin           Sec.Offset - Sec.ParentSegment->Offset + Sec.ParentSegment->PAddr;
274025d7b4fbSAlexey Lapshin     if (Sec.Type != SHT_NOBITS && Sec.Size > 0)
274125d7b4fbSAlexey Lapshin       MinAddr = std::min(MinAddr, Sec.Addr);
274225d7b4fbSAlexey Lapshin   }
274325d7b4fbSAlexey Lapshin 
274425d7b4fbSAlexey Lapshin   // Now that every section has been laid out we just need to compute the total
274525d7b4fbSAlexey Lapshin   // file size. This might not be the same as the offset returned by
274625d7b4fbSAlexey Lapshin   // layoutSections, because we want to truncate the last segment to the end of
274725d7b4fbSAlexey Lapshin   // its last non-empty section, to match GNU objcopy's behaviour.
27484070dffdSquic-akaryaki   TotalSize = PadTo > MinAddr ? PadTo - MinAddr : 0;
274925d7b4fbSAlexey Lapshin   for (SectionBase &Sec : Obj.allocSections())
275025d7b4fbSAlexey Lapshin     if (Sec.Type != SHT_NOBITS && Sec.Size > 0) {
275125d7b4fbSAlexey Lapshin       Sec.Offset = Sec.Addr - MinAddr;
275225d7b4fbSAlexey Lapshin       TotalSize = std::max(TotalSize, Sec.Offset + Sec.Size);
275325d7b4fbSAlexey Lapshin     }
275425d7b4fbSAlexey Lapshin 
275525d7b4fbSAlexey Lapshin   Buf = WritableMemoryBuffer::getNewMemBuffer(TotalSize);
275625d7b4fbSAlexey Lapshin   if (!Buf)
275725d7b4fbSAlexey Lapshin     return createStringError(errc::not_enough_memory,
275825d7b4fbSAlexey Lapshin                              "failed to allocate memory buffer of " +
275925d7b4fbSAlexey Lapshin                                  Twine::utohexstr(TotalSize) + " bytes");
276025d7b4fbSAlexey Lapshin   SecWriter = std::make_unique<BinarySectionWriter>(*Buf);
276125d7b4fbSAlexey Lapshin   return Error::success();
276225d7b4fbSAlexey Lapshin }
276325d7b4fbSAlexey Lapshin 
27647ddc3205Squic-areg Error ASCIIHexWriter::checkSection(const SectionBase &S) const {
27657ddc3205Squic-areg   if (addressOverflows32bit(S.Addr) ||
27667ddc3205Squic-areg       addressOverflows32bit(S.Addr + S.Size - 1))
27677ddc3205Squic-areg     return createStringError(
27687ddc3205Squic-areg         errc::invalid_argument,
27697ddc3205Squic-areg         "section '%s' address range [0x%llx, 0x%llx] is not 32 bit",
27707ddc3205Squic-areg         S.Name.c_str(), S.Addr, S.Addr + S.Size - 1);
27717ddc3205Squic-areg   return Error::success();
27727ddc3205Squic-areg }
27737ddc3205Squic-areg 
27747ddc3205Squic-areg Error ASCIIHexWriter::finalize() {
27757ddc3205Squic-areg   // We can't write 64-bit addresses.
27767ddc3205Squic-areg   if (addressOverflows32bit(Obj.Entry))
27777ddc3205Squic-areg     return createStringError(errc::invalid_argument,
27787ddc3205Squic-areg                              "entry point address 0x%llx overflows 32 bits",
27797ddc3205Squic-areg                              Obj.Entry);
27807ddc3205Squic-areg 
27817ddc3205Squic-areg   for (const SectionBase &S : Obj.sections()) {
27827ddc3205Squic-areg     if ((S.Flags & ELF::SHF_ALLOC) && S.Type != ELF::SHT_NOBITS && S.Size > 0) {
27837ddc3205Squic-areg       if (Error E = checkSection(S))
27847ddc3205Squic-areg         return E;
27857ddc3205Squic-areg       Sections.push_back(&S);
27867ddc3205Squic-areg     }
27877ddc3205Squic-areg   }
27887ddc3205Squic-areg 
27897ddc3205Squic-areg   llvm::sort(Sections, [](const SectionBase *A, const SectionBase *B) {
27907ddc3205Squic-areg     return sectionPhysicalAddr(A) < sectionPhysicalAddr(B);
27917ddc3205Squic-areg   });
27927ddc3205Squic-areg 
27937ddc3205Squic-areg   std::unique_ptr<WritableMemoryBuffer> EmptyBuffer =
27947ddc3205Squic-areg       WritableMemoryBuffer::getNewMemBuffer(0);
27957ddc3205Squic-areg   if (!EmptyBuffer)
27967ddc3205Squic-areg     return createStringError(errc::not_enough_memory,
27977ddc3205Squic-areg                              "failed to allocate memory buffer of 0 bytes");
27987ddc3205Squic-areg 
27997ddc3205Squic-areg   Expected<size_t> ExpTotalSize = getTotalSize(*EmptyBuffer);
28007ddc3205Squic-areg   if (!ExpTotalSize)
28017ddc3205Squic-areg     return ExpTotalSize.takeError();
28027ddc3205Squic-areg   TotalSize = *ExpTotalSize;
28037ddc3205Squic-areg 
28047ddc3205Squic-areg   Buf = WritableMemoryBuffer::getNewMemBuffer(TotalSize);
28057ddc3205Squic-areg   if (!Buf)
28067ddc3205Squic-areg     return createStringError(errc::not_enough_memory,
28077ddc3205Squic-areg                              "failed to allocate memory buffer of 0x" +
28087ddc3205Squic-areg                                  Twine::utohexstr(TotalSize) + " bytes");
28097ddc3205Squic-areg   return Error::success();
281025d7b4fbSAlexey Lapshin }
281125d7b4fbSAlexey Lapshin 
281225d7b4fbSAlexey Lapshin uint64_t IHexWriter::writeEntryPointRecord(uint8_t *Buf) {
281325d7b4fbSAlexey Lapshin   IHexLineData HexData;
281425d7b4fbSAlexey Lapshin   uint8_t Data[4] = {};
281525d7b4fbSAlexey Lapshin   // We don't write entry point record if entry is zero.
281625d7b4fbSAlexey Lapshin   if (Obj.Entry == 0)
281725d7b4fbSAlexey Lapshin     return 0;
281825d7b4fbSAlexey Lapshin 
281925d7b4fbSAlexey Lapshin   if (Obj.Entry <= 0xFFFFFU) {
282025d7b4fbSAlexey Lapshin     Data[0] = ((Obj.Entry & 0xF0000U) >> 12) & 0xFF;
282125d7b4fbSAlexey Lapshin     support::endian::write(&Data[2], static_cast<uint16_t>(Obj.Entry),
28224a0ccfa8SKazu Hirata                            llvm::endianness::big);
282325d7b4fbSAlexey Lapshin     HexData = IHexRecord::getLine(IHexRecord::StartAddr80x86, 0, Data);
282425d7b4fbSAlexey Lapshin   } else {
282525d7b4fbSAlexey Lapshin     support::endian::write(Data, static_cast<uint32_t>(Obj.Entry),
28264a0ccfa8SKazu Hirata                            llvm::endianness::big);
282725d7b4fbSAlexey Lapshin     HexData = IHexRecord::getLine(IHexRecord::StartAddr, 0, Data);
282825d7b4fbSAlexey Lapshin   }
282925d7b4fbSAlexey Lapshin   memcpy(Buf, HexData.data(), HexData.size());
283025d7b4fbSAlexey Lapshin   return HexData.size();
283125d7b4fbSAlexey Lapshin }
283225d7b4fbSAlexey Lapshin 
283325d7b4fbSAlexey Lapshin uint64_t IHexWriter::writeEndOfFileRecord(uint8_t *Buf) {
283425d7b4fbSAlexey Lapshin   IHexLineData HexData = IHexRecord::getLine(IHexRecord::EndOfFile, 0, {});
283525d7b4fbSAlexey Lapshin   memcpy(Buf, HexData.data(), HexData.size());
283625d7b4fbSAlexey Lapshin   return HexData.size();
283725d7b4fbSAlexey Lapshin }
283825d7b4fbSAlexey Lapshin 
28397ddc3205Squic-areg Expected<size_t>
28407ddc3205Squic-areg IHexWriter::getTotalSize(WritableMemoryBuffer &EmptyBuffer) const {
28417ddc3205Squic-areg   IHexSectionWriterBase LengthCalc(EmptyBuffer);
28427ddc3205Squic-areg   for (const SectionBase *Sec : Sections)
28437ddc3205Squic-areg     if (Error Err = Sec->accept(LengthCalc))
28445afbed19SJon Roelofs       return std::move(Err);
28457ddc3205Squic-areg 
28467ddc3205Squic-areg   // We need space to write section records + StartAddress record
28477ddc3205Squic-areg   // (if start adress is not zero) + EndOfFile record.
28487ddc3205Squic-areg   return LengthCalc.getBufferOffset() +
28497ddc3205Squic-areg          (Obj.Entry ? IHexRecord::getLineLength(4) : 0) +
28507ddc3205Squic-areg          IHexRecord::getLineLength(0);
28517ddc3205Squic-areg }
28527ddc3205Squic-areg 
285325d7b4fbSAlexey Lapshin Error IHexWriter::write() {
285425d7b4fbSAlexey Lapshin   IHexSectionWriter Writer(*Buf);
285525d7b4fbSAlexey Lapshin   // Write sections.
285625d7b4fbSAlexey Lapshin   for (const SectionBase *Sec : Sections)
285725d7b4fbSAlexey Lapshin     if (Error Err = Sec->accept(Writer))
285825d7b4fbSAlexey Lapshin       return Err;
285925d7b4fbSAlexey Lapshin 
286025d7b4fbSAlexey Lapshin   uint64_t Offset = Writer.getBufferOffset();
286125d7b4fbSAlexey Lapshin   // Write entry point address.
286225d7b4fbSAlexey Lapshin   Offset += writeEntryPointRecord(
286325d7b4fbSAlexey Lapshin       reinterpret_cast<uint8_t *>(Buf->getBufferStart()) + Offset);
286425d7b4fbSAlexey Lapshin   // Write EOF.
286525d7b4fbSAlexey Lapshin   Offset += writeEndOfFileRecord(
286625d7b4fbSAlexey Lapshin       reinterpret_cast<uint8_t *>(Buf->getBufferStart()) + Offset);
286725d7b4fbSAlexey Lapshin   assert(Offset == TotalSize);
286825d7b4fbSAlexey Lapshin 
286925d7b4fbSAlexey Lapshin   // TODO: Implement direct writing to the output stream (without intermediate
287025d7b4fbSAlexey Lapshin   // memory buffer Buf).
287125d7b4fbSAlexey Lapshin   Out.write(Buf->getBufferStart(), Buf->getBufferSize());
287225d7b4fbSAlexey Lapshin   return Error::success();
287325d7b4fbSAlexey Lapshin }
287425d7b4fbSAlexey Lapshin 
28757ddc3205Squic-areg Error SRECSectionWriterBase::visit(const StringTableSection &Sec) {
28767ddc3205Squic-areg   // Check that the sizer has already done its work.
28777ddc3205Squic-areg   assert(Sec.Size == Sec.StrTabBuilder.getSize() &&
28787ddc3205Squic-areg          "Expected section size to have been finalized");
28797ddc3205Squic-areg   // We don't need to write anything here because the real writer has already
28807ddc3205Squic-areg   // done it.
288125d7b4fbSAlexey Lapshin   return Error::success();
288225d7b4fbSAlexey Lapshin }
288325d7b4fbSAlexey Lapshin 
28847ddc3205Squic-areg Error SRECSectionWriterBase::visit(const Section &Sec) {
28857ddc3205Squic-areg   writeSection(Sec, Sec.Contents);
28867ddc3205Squic-areg   return Error::success();
288725d7b4fbSAlexey Lapshin }
288825d7b4fbSAlexey Lapshin 
28897ddc3205Squic-areg Error SRECSectionWriterBase::visit(const OwnedDataSection &Sec) {
28907ddc3205Squic-areg   writeSection(Sec, Sec.Data);
28917ddc3205Squic-areg   return Error::success();
28927ddc3205Squic-areg }
289325d7b4fbSAlexey Lapshin 
28947ddc3205Squic-areg Error SRECSectionWriterBase::visit(const DynamicRelocationSection &Sec) {
28957ddc3205Squic-areg   writeSection(Sec, Sec.Contents);
28967ddc3205Squic-areg   return Error::success();
28977ddc3205Squic-areg }
28987ddc3205Squic-areg 
28997ddc3205Squic-areg void SRECSectionWriter::writeRecord(SRecord &Record, uint64_t Off) {
29007ddc3205Squic-areg   SRecLineData Data = Record.toString();
29017ddc3205Squic-areg   memcpy(Out.getBufferStart() + Off, Data.data(), Data.size());
29027ddc3205Squic-areg }
29037ddc3205Squic-areg 
29047ddc3205Squic-areg void SRECSectionWriterBase::writeRecords(uint32_t Entry) {
29057ddc3205Squic-areg   // The ELF header could contain an entry point outside of the sections we have
29067ddc3205Squic-areg   // seen that does not fit the current record Type.
29077ddc3205Squic-areg   Type = std::max(Type, SRecord::getType(Entry));
29087ddc3205Squic-areg   uint64_t Off = HeaderSize;
29097ddc3205Squic-areg   for (SRecord &Record : Records) {
29107ddc3205Squic-areg     Record.Type = Type;
29117ddc3205Squic-areg     writeRecord(Record, Off);
29127ddc3205Squic-areg     Off += Record.getSize();
29137ddc3205Squic-areg   }
29147ddc3205Squic-areg   Offset = Off;
29157ddc3205Squic-areg }
29167ddc3205Squic-areg 
29177ddc3205Squic-areg void SRECSectionWriterBase::writeSection(const SectionBase &S,
29187ddc3205Squic-areg                                          ArrayRef<uint8_t> Data) {
29197ddc3205Squic-areg   const uint32_t ChunkSize = 16;
29207ddc3205Squic-areg   uint32_t Address = sectionPhysicalAddr(&S);
29217ddc3205Squic-areg   uint32_t EndAddr = Address + S.Size - 1;
29227ddc3205Squic-areg   Type = std::max(SRecord::getType(EndAddr), Type);
29237ddc3205Squic-areg   while (!Data.empty()) {
29247ddc3205Squic-areg     uint64_t DataSize = std::min<uint64_t>(Data.size(), ChunkSize);
29257ddc3205Squic-areg     SRecord Record{Type, Address, Data.take_front(DataSize)};
29267ddc3205Squic-areg     Records.push_back(Record);
29277ddc3205Squic-areg     Data = Data.drop_front(DataSize);
29287ddc3205Squic-areg     Address += DataSize;
29297ddc3205Squic-areg   }
29307ddc3205Squic-areg }
29317ddc3205Squic-areg 
29327ddc3205Squic-areg Error SRECSectionWriter::visit(const StringTableSection &Sec) {
29337ddc3205Squic-areg   assert(Sec.Size == Sec.StrTabBuilder.getSize() &&
29347ddc3205Squic-areg          "Section size does not match the section's string table builder size");
29357ddc3205Squic-areg   std::vector<uint8_t> Data(Sec.Size);
29367ddc3205Squic-areg   Sec.StrTabBuilder.write(Data.data());
29377ddc3205Squic-areg   writeSection(Sec, Data);
29387ddc3205Squic-areg   return Error::success();
29397ddc3205Squic-areg }
29407ddc3205Squic-areg 
29417ddc3205Squic-areg SRecLineData SRecord::toString() const {
29427ddc3205Squic-areg   SRecLineData Line(getSize());
29437ddc3205Squic-areg   auto *Iter = Line.begin();
29447ddc3205Squic-areg   *Iter++ = 'S';
29457ddc3205Squic-areg   *Iter++ = '0' + Type;
29467ddc3205Squic-areg   // Write 1 byte (2 hex characters) record count.
29477ddc3205Squic-areg   Iter = toHexStr(getCount(), Iter, 2);
29487ddc3205Squic-areg   // Write the address field with length depending on record type.
29497ddc3205Squic-areg   Iter = toHexStr(Address, Iter, getAddressSize());
29507ddc3205Squic-areg   // Write data byte by byte.
29517ddc3205Squic-areg   for (uint8_t X : Data)
29527ddc3205Squic-areg     Iter = toHexStr(X, Iter, 2);
29537ddc3205Squic-areg   // Write the 1 byte checksum.
29547ddc3205Squic-areg   Iter = toHexStr(getChecksum(), Iter, 2);
29557ddc3205Squic-areg   *Iter++ = '\r';
29567ddc3205Squic-areg   *Iter++ = '\n';
29577ddc3205Squic-areg   assert(Iter == Line.end());
29587ddc3205Squic-areg   return Line;
29597ddc3205Squic-areg }
29607ddc3205Squic-areg 
29617ddc3205Squic-areg uint8_t SRecord::getChecksum() const {
29627ddc3205Squic-areg   uint32_t Sum = getCount();
29637ddc3205Squic-areg   Sum += (Address >> 24) & 0xFF;
29647ddc3205Squic-areg   Sum += (Address >> 16) & 0xFF;
29657ddc3205Squic-areg   Sum += (Address >> 8) & 0xFF;
29667ddc3205Squic-areg   Sum += Address & 0xFF;
29677ddc3205Squic-areg   for (uint8_t Byte : Data)
29687ddc3205Squic-areg     Sum += Byte;
29697ddc3205Squic-areg   return 0xFF - (Sum & 0xFF);
29707ddc3205Squic-areg }
29717ddc3205Squic-areg 
29727ddc3205Squic-areg size_t SRecord::getSize() const {
29737ddc3205Squic-areg   // Type, Count, Checksum, and CRLF are two characters each.
29747ddc3205Squic-areg   return 2 + 2 + getAddressSize() + Data.size() * 2 + 2 + 2;
29757ddc3205Squic-areg }
29767ddc3205Squic-areg 
29777ddc3205Squic-areg uint8_t SRecord::getAddressSize() const {
29787ddc3205Squic-areg   switch (Type) {
29797ddc3205Squic-areg   case Type::S2:
29807ddc3205Squic-areg     return 6;
29817ddc3205Squic-areg   case Type::S3:
29827ddc3205Squic-areg     return 8;
29837ddc3205Squic-areg   case Type::S7:
29847ddc3205Squic-areg     return 8;
29857ddc3205Squic-areg   case Type::S8:
29867ddc3205Squic-areg     return 6;
29877ddc3205Squic-areg   default:
29887ddc3205Squic-areg     return 4;
29897ddc3205Squic-areg   }
29907ddc3205Squic-areg }
29917ddc3205Squic-areg 
29927ddc3205Squic-areg uint8_t SRecord::getCount() const {
29937ddc3205Squic-areg   uint8_t DataSize = Data.size();
29947ddc3205Squic-areg   uint8_t ChecksumSize = 1;
29957ddc3205Squic-areg   return getAddressSize() / 2 + DataSize + ChecksumSize;
29967ddc3205Squic-areg }
29977ddc3205Squic-areg 
29987ddc3205Squic-areg uint8_t SRecord::getType(uint32_t Address) {
29997ddc3205Squic-areg   if (isUInt<16>(Address))
30007ddc3205Squic-areg     return SRecord::S1;
30017ddc3205Squic-areg   if (isUInt<24>(Address))
30027ddc3205Squic-areg     return SRecord::S2;
30037ddc3205Squic-areg   return SRecord::S3;
30047ddc3205Squic-areg }
30057ddc3205Squic-areg 
30067ddc3205Squic-areg SRecord SRecord::getHeader(StringRef FileName) {
30077ddc3205Squic-areg   // Header is a record with Type S0, Address 0, and Data that is a
30087ddc3205Squic-areg   // vendor-specific text comment. For the comment we will use the output file
30097ddc3205Squic-areg   // name truncated to 40 characters to match the behavior of GNU objcopy.
30107ddc3205Squic-areg   StringRef HeaderContents = FileName.slice(0, 40);
30117ddc3205Squic-areg   ArrayRef<uint8_t> Data(
30127ddc3205Squic-areg       reinterpret_cast<const uint8_t *>(HeaderContents.data()),
30137ddc3205Squic-areg       HeaderContents.size());
30147ddc3205Squic-areg   return {SRecord::S0, 0, Data};
30157ddc3205Squic-areg }
30167ddc3205Squic-areg 
30177ddc3205Squic-areg size_t SRECWriter::writeHeader(uint8_t *Buf) {
30187ddc3205Squic-areg   SRecLineData Record = SRecord::getHeader(OutputFileName).toString();
30197ddc3205Squic-areg   memcpy(Buf, Record.data(), Record.size());
30207ddc3205Squic-areg   return Record.size();
30217ddc3205Squic-areg }
30227ddc3205Squic-areg 
30237ddc3205Squic-areg size_t SRECWriter::writeTerminator(uint8_t *Buf, uint8_t Type) {
30247ddc3205Squic-areg   assert(Type >= SRecord::S7 && Type <= SRecord::S9 &&
30257ddc3205Squic-areg          "Invalid record type for terminator");
30267ddc3205Squic-areg   uint32_t Entry = Obj.Entry;
30277ddc3205Squic-areg   SRecLineData Data = SRecord{Type, Entry, {}}.toString();
30287ddc3205Squic-areg   memcpy(Buf, Data.data(), Data.size());
30297ddc3205Squic-areg   return Data.size();
30307ddc3205Squic-areg }
30317ddc3205Squic-areg 
30327ddc3205Squic-areg Expected<size_t>
30337ddc3205Squic-areg SRECWriter::getTotalSize(WritableMemoryBuffer &EmptyBuffer) const {
30347ddc3205Squic-areg   SRECSizeCalculator SizeCalc(EmptyBuffer, 0);
303525d7b4fbSAlexey Lapshin   for (const SectionBase *Sec : Sections)
30367ddc3205Squic-areg     if (Error Err = Sec->accept(SizeCalc))
30372cbe5a33SMaksim Panchenko       return std::move(Err);
303825d7b4fbSAlexey Lapshin 
30397ddc3205Squic-areg   SizeCalc.writeRecords(Obj.Entry);
30407ddc3205Squic-areg   // We need to add the size of the Header and Terminator records.
30417ddc3205Squic-areg   SRecord Header = SRecord::getHeader(OutputFileName);
30427ddc3205Squic-areg   uint8_t TerminatorType = 10 - SizeCalc.getType();
30437ddc3205Squic-areg   SRecord Terminator = {TerminatorType, static_cast<uint32_t>(Obj.Entry), {}};
30447ddc3205Squic-areg   return Header.getSize() + SizeCalc.getBufferOffset() + Terminator.getSize();
30457ddc3205Squic-areg }
304625d7b4fbSAlexey Lapshin 
30477ddc3205Squic-areg Error SRECWriter::write() {
30487ddc3205Squic-areg   uint32_t HeaderSize =
30497ddc3205Squic-areg       writeHeader(reinterpret_cast<uint8_t *>(Buf->getBufferStart()));
30507ddc3205Squic-areg   SRECSectionWriter Writer(*Buf, HeaderSize);
30517ddc3205Squic-areg   for (const SectionBase *S : Sections) {
30527ddc3205Squic-areg     if (Error E = S->accept(Writer))
30537ddc3205Squic-areg       return E;
30547ddc3205Squic-areg   }
30557ddc3205Squic-areg   Writer.writeRecords(Obj.Entry);
30567ddc3205Squic-areg   uint64_t Offset = Writer.getBufferOffset();
305725d7b4fbSAlexey Lapshin 
30587ddc3205Squic-areg   // An S1 record terminates with an S9 record, S2 with S8, and S3 with S7.
30597ddc3205Squic-areg   uint8_t TerminatorType = 10 - Writer.getType();
30607ddc3205Squic-areg   Offset += writeTerminator(
30617ddc3205Squic-areg       reinterpret_cast<uint8_t *>(Buf->getBufferStart() + Offset),
30627ddc3205Squic-areg       TerminatorType);
30637ddc3205Squic-areg   assert(Offset == TotalSize);
30647ddc3205Squic-areg   Out.write(Buf->getBufferStart(), Buf->getBufferSize());
306525d7b4fbSAlexey Lapshin   return Error::success();
306625d7b4fbSAlexey Lapshin }
306725d7b4fbSAlexey Lapshin 
306825d7b4fbSAlexey Lapshin namespace llvm {
306925d7b4fbSAlexey Lapshin namespace objcopy {
307025d7b4fbSAlexey Lapshin namespace elf {
307125d7b4fbSAlexey Lapshin 
307225d7b4fbSAlexey Lapshin template class ELFBuilder<ELF64LE>;
307325d7b4fbSAlexey Lapshin template class ELFBuilder<ELF64BE>;
307425d7b4fbSAlexey Lapshin template class ELFBuilder<ELF32LE>;
307525d7b4fbSAlexey Lapshin template class ELFBuilder<ELF32BE>;
307625d7b4fbSAlexey Lapshin 
307725d7b4fbSAlexey Lapshin template class ELFWriter<ELF64LE>;
307825d7b4fbSAlexey Lapshin template class ELFWriter<ELF64BE>;
307925d7b4fbSAlexey Lapshin template class ELFWriter<ELF32LE>;
308025d7b4fbSAlexey Lapshin template class ELFWriter<ELF32BE>;
308125d7b4fbSAlexey Lapshin 
308225d7b4fbSAlexey Lapshin } // end namespace elf
308325d7b4fbSAlexey Lapshin } // end namespace objcopy
308425d7b4fbSAlexey Lapshin } // end namespace llvm
3085