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"
1625d7b4fbSAlexey Lapshin #include "llvm/MC/MCTargetOptions.h"
1725d7b4fbSAlexey Lapshin #include "llvm/Object/ELF.h"
1825d7b4fbSAlexey Lapshin #include "llvm/Object/ELFObjectFile.h"
1925d7b4fbSAlexey Lapshin #include "llvm/Support/Compression.h"
2025d7b4fbSAlexey Lapshin #include "llvm/Support/Endian.h"
2125d7b4fbSAlexey Lapshin #include "llvm/Support/ErrorHandling.h"
2225d7b4fbSAlexey Lapshin #include "llvm/Support/FileOutputBuffer.h"
2325d7b4fbSAlexey Lapshin #include "llvm/Support/Path.h"
2425d7b4fbSAlexey Lapshin #include <algorithm>
2525d7b4fbSAlexey Lapshin #include <cstddef>
2625d7b4fbSAlexey Lapshin #include <cstdint>
2725d7b4fbSAlexey Lapshin #include <iterator>
2825d7b4fbSAlexey Lapshin #include <unordered_set>
2925d7b4fbSAlexey Lapshin #include <utility>
3025d7b4fbSAlexey Lapshin #include <vector>
3125d7b4fbSAlexey Lapshin 
3225d7b4fbSAlexey Lapshin using namespace llvm;
3325d7b4fbSAlexey Lapshin using namespace llvm::ELF;
3425d7b4fbSAlexey Lapshin using namespace llvm::objcopy::elf;
3525d7b4fbSAlexey Lapshin using namespace llvm::object;
3625d7b4fbSAlexey Lapshin 
writePhdr(const Segment & Seg)3725d7b4fbSAlexey Lapshin template <class ELFT> void ELFWriter<ELFT>::writePhdr(const Segment &Seg) {
3825d7b4fbSAlexey Lapshin   uint8_t *B = reinterpret_cast<uint8_t *>(Buf->getBufferStart()) +
3925d7b4fbSAlexey Lapshin                Obj.ProgramHdrSegment.Offset + Seg.Index * sizeof(Elf_Phdr);
4025d7b4fbSAlexey Lapshin   Elf_Phdr &Phdr = *reinterpret_cast<Elf_Phdr *>(B);
4125d7b4fbSAlexey Lapshin   Phdr.p_type = Seg.Type;
4225d7b4fbSAlexey Lapshin   Phdr.p_flags = Seg.Flags;
4325d7b4fbSAlexey Lapshin   Phdr.p_offset = Seg.Offset;
4425d7b4fbSAlexey Lapshin   Phdr.p_vaddr = Seg.VAddr;
4525d7b4fbSAlexey Lapshin   Phdr.p_paddr = Seg.PAddr;
4625d7b4fbSAlexey Lapshin   Phdr.p_filesz = Seg.FileSize;
4725d7b4fbSAlexey Lapshin   Phdr.p_memsz = Seg.MemSize;
4825d7b4fbSAlexey Lapshin   Phdr.p_align = Seg.Align;
4925d7b4fbSAlexey Lapshin }
5025d7b4fbSAlexey Lapshin 
removeSectionReferences(bool,function_ref<bool (const SectionBase *)>)5125d7b4fbSAlexey Lapshin Error SectionBase::removeSectionReferences(
5225d7b4fbSAlexey Lapshin     bool, function_ref<bool(const SectionBase *)>) {
5325d7b4fbSAlexey Lapshin   return Error::success();
5425d7b4fbSAlexey Lapshin }
5525d7b4fbSAlexey Lapshin 
removeSymbols(function_ref<bool (const Symbol &)>)5625d7b4fbSAlexey Lapshin Error SectionBase::removeSymbols(function_ref<bool(const Symbol &)>) {
5725d7b4fbSAlexey Lapshin   return Error::success();
5825d7b4fbSAlexey Lapshin }
5925d7b4fbSAlexey Lapshin 
initialize(SectionTableRef)6025d7b4fbSAlexey Lapshin Error SectionBase::initialize(SectionTableRef) { return Error::success(); }
finalize()6125d7b4fbSAlexey Lapshin void SectionBase::finalize() {}
markSymbols()6225d7b4fbSAlexey Lapshin void SectionBase::markSymbols() {}
replaceSectionReferences(const DenseMap<SectionBase *,SectionBase * > &)6325d7b4fbSAlexey Lapshin void SectionBase::replaceSectionReferences(
6425d7b4fbSAlexey Lapshin     const DenseMap<SectionBase *, SectionBase *> &) {}
onRemove()6525d7b4fbSAlexey Lapshin void SectionBase::onRemove() {}
6625d7b4fbSAlexey Lapshin 
writeShdr(const SectionBase & Sec)6725d7b4fbSAlexey Lapshin template <class ELFT> void ELFWriter<ELFT>::writeShdr(const SectionBase &Sec) {
6825d7b4fbSAlexey Lapshin   uint8_t *B =
6925d7b4fbSAlexey Lapshin       reinterpret_cast<uint8_t *>(Buf->getBufferStart()) + Sec.HeaderOffset;
7025d7b4fbSAlexey Lapshin   Elf_Shdr &Shdr = *reinterpret_cast<Elf_Shdr *>(B);
7125d7b4fbSAlexey Lapshin   Shdr.sh_name = Sec.NameIndex;
7225d7b4fbSAlexey Lapshin   Shdr.sh_type = Sec.Type;
7325d7b4fbSAlexey Lapshin   Shdr.sh_flags = Sec.Flags;
7425d7b4fbSAlexey Lapshin   Shdr.sh_addr = Sec.Addr;
7525d7b4fbSAlexey Lapshin   Shdr.sh_offset = Sec.Offset;
7625d7b4fbSAlexey Lapshin   Shdr.sh_size = Sec.Size;
7725d7b4fbSAlexey Lapshin   Shdr.sh_link = Sec.Link;
7825d7b4fbSAlexey Lapshin   Shdr.sh_info = Sec.Info;
7925d7b4fbSAlexey Lapshin   Shdr.sh_addralign = Sec.Align;
8025d7b4fbSAlexey Lapshin   Shdr.sh_entsize = Sec.EntrySize;
8125d7b4fbSAlexey Lapshin }
8225d7b4fbSAlexey Lapshin 
visit(Section &)8325d7b4fbSAlexey Lapshin template <class ELFT> Error ELFSectionSizer<ELFT>::visit(Section &) {
8425d7b4fbSAlexey Lapshin   return Error::success();
8525d7b4fbSAlexey Lapshin }
8625d7b4fbSAlexey Lapshin 
visit(OwnedDataSection &)8725d7b4fbSAlexey Lapshin template <class ELFT> Error ELFSectionSizer<ELFT>::visit(OwnedDataSection &) {
8825d7b4fbSAlexey Lapshin   return Error::success();
8925d7b4fbSAlexey Lapshin }
9025d7b4fbSAlexey Lapshin 
visit(StringTableSection &)9125d7b4fbSAlexey Lapshin template <class ELFT> Error ELFSectionSizer<ELFT>::visit(StringTableSection &) {
9225d7b4fbSAlexey Lapshin   return Error::success();
9325d7b4fbSAlexey Lapshin }
9425d7b4fbSAlexey Lapshin 
9525d7b4fbSAlexey Lapshin template <class ELFT>
visit(DynamicRelocationSection &)9625d7b4fbSAlexey Lapshin Error ELFSectionSizer<ELFT>::visit(DynamicRelocationSection &) {
9725d7b4fbSAlexey Lapshin   return Error::success();
9825d7b4fbSAlexey Lapshin }
9925d7b4fbSAlexey Lapshin 
10025d7b4fbSAlexey Lapshin template <class ELFT>
visit(SymbolTableSection & Sec)10125d7b4fbSAlexey Lapshin Error ELFSectionSizer<ELFT>::visit(SymbolTableSection &Sec) {
10225d7b4fbSAlexey Lapshin   Sec.EntrySize = sizeof(Elf_Sym);
10325d7b4fbSAlexey Lapshin   Sec.Size = Sec.Symbols.size() * Sec.EntrySize;
10425d7b4fbSAlexey Lapshin   // Align to the largest field in Elf_Sym.
10525d7b4fbSAlexey Lapshin   Sec.Align = ELFT::Is64Bits ? sizeof(Elf_Xword) : sizeof(Elf_Word);
10625d7b4fbSAlexey Lapshin   return Error::success();
10725d7b4fbSAlexey Lapshin }
10825d7b4fbSAlexey Lapshin 
10925d7b4fbSAlexey Lapshin template <class ELFT>
visit(RelocationSection & Sec)11025d7b4fbSAlexey Lapshin Error ELFSectionSizer<ELFT>::visit(RelocationSection &Sec) {
11125d7b4fbSAlexey Lapshin   Sec.EntrySize = Sec.Type == SHT_REL ? sizeof(Elf_Rel) : sizeof(Elf_Rela);
11225d7b4fbSAlexey Lapshin   Sec.Size = Sec.Relocations.size() * Sec.EntrySize;
11325d7b4fbSAlexey Lapshin   // Align to the largest field in Elf_Rel(a).
11425d7b4fbSAlexey Lapshin   Sec.Align = ELFT::Is64Bits ? sizeof(Elf_Xword) : sizeof(Elf_Word);
11525d7b4fbSAlexey Lapshin   return Error::success();
11625d7b4fbSAlexey Lapshin }
11725d7b4fbSAlexey Lapshin 
11825d7b4fbSAlexey Lapshin template <class ELFT>
visit(GnuDebugLinkSection &)11925d7b4fbSAlexey Lapshin Error ELFSectionSizer<ELFT>::visit(GnuDebugLinkSection &) {
12025d7b4fbSAlexey Lapshin   return Error::success();
12125d7b4fbSAlexey Lapshin }
12225d7b4fbSAlexey Lapshin 
visit(GroupSection & Sec)12325d7b4fbSAlexey Lapshin template <class ELFT> Error ELFSectionSizer<ELFT>::visit(GroupSection &Sec) {
12425d7b4fbSAlexey Lapshin   Sec.Size = sizeof(Elf_Word) + Sec.GroupMembers.size() * sizeof(Elf_Word);
12525d7b4fbSAlexey Lapshin   return Error::success();
12625d7b4fbSAlexey Lapshin }
12725d7b4fbSAlexey Lapshin 
12825d7b4fbSAlexey Lapshin template <class ELFT>
visit(SectionIndexSection &)12925d7b4fbSAlexey Lapshin Error ELFSectionSizer<ELFT>::visit(SectionIndexSection &) {
13025d7b4fbSAlexey Lapshin   return Error::success();
13125d7b4fbSAlexey Lapshin }
13225d7b4fbSAlexey Lapshin 
visit(CompressedSection &)13325d7b4fbSAlexey Lapshin template <class ELFT> Error ELFSectionSizer<ELFT>::visit(CompressedSection &) {
13425d7b4fbSAlexey Lapshin   return Error::success();
13525d7b4fbSAlexey Lapshin }
13625d7b4fbSAlexey Lapshin 
13725d7b4fbSAlexey Lapshin template <class ELFT>
visit(DecompressedSection &)13825d7b4fbSAlexey Lapshin Error ELFSectionSizer<ELFT>::visit(DecompressedSection &) {
13925d7b4fbSAlexey Lapshin   return Error::success();
14025d7b4fbSAlexey Lapshin }
14125d7b4fbSAlexey Lapshin 
visit(const SectionIndexSection & Sec)14225d7b4fbSAlexey Lapshin Error BinarySectionWriter::visit(const SectionIndexSection &Sec) {
14325d7b4fbSAlexey Lapshin   return createStringError(errc::operation_not_permitted,
14425d7b4fbSAlexey Lapshin                            "cannot write symbol section index table '" +
14525d7b4fbSAlexey Lapshin                                Sec.Name + "' ");
14625d7b4fbSAlexey Lapshin }
14725d7b4fbSAlexey Lapshin 
visit(const SymbolTableSection & Sec)14825d7b4fbSAlexey Lapshin Error BinarySectionWriter::visit(const SymbolTableSection &Sec) {
14925d7b4fbSAlexey Lapshin   return createStringError(errc::operation_not_permitted,
15025d7b4fbSAlexey Lapshin                            "cannot write symbol table '" + Sec.Name +
15125d7b4fbSAlexey Lapshin                                "' out to binary");
15225d7b4fbSAlexey Lapshin }
15325d7b4fbSAlexey Lapshin 
visit(const RelocationSection & Sec)15425d7b4fbSAlexey Lapshin Error BinarySectionWriter::visit(const RelocationSection &Sec) {
15525d7b4fbSAlexey Lapshin   return createStringError(errc::operation_not_permitted,
15625d7b4fbSAlexey Lapshin                            "cannot write relocation section '" + Sec.Name +
15725d7b4fbSAlexey Lapshin                                "' out to binary");
15825d7b4fbSAlexey Lapshin }
15925d7b4fbSAlexey Lapshin 
visit(const GnuDebugLinkSection & Sec)16025d7b4fbSAlexey Lapshin Error BinarySectionWriter::visit(const GnuDebugLinkSection &Sec) {
16125d7b4fbSAlexey Lapshin   return createStringError(errc::operation_not_permitted,
16225d7b4fbSAlexey Lapshin                            "cannot write '" + Sec.Name + "' out to binary");
16325d7b4fbSAlexey Lapshin }
16425d7b4fbSAlexey Lapshin 
visit(const GroupSection & Sec)16525d7b4fbSAlexey Lapshin Error BinarySectionWriter::visit(const GroupSection &Sec) {
16625d7b4fbSAlexey Lapshin   return createStringError(errc::operation_not_permitted,
16725d7b4fbSAlexey Lapshin                            "cannot write '" + Sec.Name + "' out to binary");
16825d7b4fbSAlexey Lapshin }
16925d7b4fbSAlexey Lapshin 
visit(const Section & Sec)17025d7b4fbSAlexey Lapshin Error SectionWriter::visit(const Section &Sec) {
17125d7b4fbSAlexey Lapshin   if (Sec.Type != SHT_NOBITS)
17225d7b4fbSAlexey Lapshin     llvm::copy(Sec.Contents, Out.getBufferStart() + Sec.Offset);
17325d7b4fbSAlexey Lapshin 
17425d7b4fbSAlexey Lapshin   return Error::success();
17525d7b4fbSAlexey Lapshin }
17625d7b4fbSAlexey Lapshin 
addressOverflows32bit(uint64_t Addr)17725d7b4fbSAlexey Lapshin static bool addressOverflows32bit(uint64_t Addr) {
17825d7b4fbSAlexey Lapshin   // Sign extended 32 bit addresses (e.g 0xFFFFFFFF80000000) are ok
17925d7b4fbSAlexey Lapshin   return Addr > UINT32_MAX && Addr + 0x80000000 > UINT32_MAX;
18025d7b4fbSAlexey Lapshin }
18125d7b4fbSAlexey Lapshin 
checkedGetHex(StringRef S)18225d7b4fbSAlexey Lapshin template <class T> static T checkedGetHex(StringRef S) {
18325d7b4fbSAlexey Lapshin   T Value;
18425d7b4fbSAlexey Lapshin   bool Fail = S.getAsInteger(16, Value);
18525d7b4fbSAlexey Lapshin   assert(!Fail);
18625d7b4fbSAlexey Lapshin   (void)Fail;
18725d7b4fbSAlexey Lapshin   return Value;
18825d7b4fbSAlexey Lapshin }
18925d7b4fbSAlexey Lapshin 
19025d7b4fbSAlexey Lapshin // Fills exactly Len bytes of buffer with hexadecimal characters
19125d7b4fbSAlexey Lapshin // representing value 'X'
19225d7b4fbSAlexey Lapshin template <class T, class Iterator>
toHexStr(T X,Iterator It,size_t Len)19325d7b4fbSAlexey Lapshin static Iterator toHexStr(T X, Iterator It, size_t Len) {
19425d7b4fbSAlexey Lapshin   // Fill range with '0'
19525d7b4fbSAlexey Lapshin   std::fill(It, It + Len, '0');
19625d7b4fbSAlexey Lapshin 
19725d7b4fbSAlexey Lapshin   for (long I = Len - 1; I >= 0; --I) {
19825d7b4fbSAlexey Lapshin     unsigned char Mod = static_cast<unsigned char>(X) & 15;
19925d7b4fbSAlexey Lapshin     *(It + I) = hexdigit(Mod, false);
20025d7b4fbSAlexey Lapshin     X >>= 4;
20125d7b4fbSAlexey Lapshin   }
20225d7b4fbSAlexey Lapshin   assert(X == 0);
20325d7b4fbSAlexey Lapshin   return It + Len;
20425d7b4fbSAlexey Lapshin }
20525d7b4fbSAlexey Lapshin 
getChecksum(StringRef S)20625d7b4fbSAlexey Lapshin uint8_t IHexRecord::getChecksum(StringRef S) {
20725d7b4fbSAlexey Lapshin   assert((S.size() & 1) == 0);
20825d7b4fbSAlexey Lapshin   uint8_t Checksum = 0;
20925d7b4fbSAlexey Lapshin   while (!S.empty()) {
21025d7b4fbSAlexey Lapshin     Checksum += checkedGetHex<uint8_t>(S.take_front(2));
21125d7b4fbSAlexey Lapshin     S = S.drop_front(2);
21225d7b4fbSAlexey Lapshin   }
21325d7b4fbSAlexey Lapshin   return -Checksum;
21425d7b4fbSAlexey Lapshin }
21525d7b4fbSAlexey Lapshin 
getLine(uint8_t Type,uint16_t Addr,ArrayRef<uint8_t> Data)21625d7b4fbSAlexey Lapshin IHexLineData IHexRecord::getLine(uint8_t Type, uint16_t Addr,
21725d7b4fbSAlexey Lapshin                                  ArrayRef<uint8_t> Data) {
21825d7b4fbSAlexey Lapshin   IHexLineData Line(getLineLength(Data.size()));
21925d7b4fbSAlexey Lapshin   assert(Line.size());
22025d7b4fbSAlexey Lapshin   auto Iter = Line.begin();
22125d7b4fbSAlexey Lapshin   *Iter++ = ':';
22225d7b4fbSAlexey Lapshin   Iter = toHexStr(Data.size(), Iter, 2);
22325d7b4fbSAlexey Lapshin   Iter = toHexStr(Addr, Iter, 4);
22425d7b4fbSAlexey Lapshin   Iter = toHexStr(Type, Iter, 2);
22525d7b4fbSAlexey Lapshin   for (uint8_t X : Data)
22625d7b4fbSAlexey Lapshin     Iter = toHexStr(X, Iter, 2);
22725d7b4fbSAlexey Lapshin   StringRef S(Line.data() + 1, std::distance(Line.begin() + 1, Iter));
22825d7b4fbSAlexey Lapshin   Iter = toHexStr(getChecksum(S), Iter, 2);
22925d7b4fbSAlexey Lapshin   *Iter++ = '\r';
23025d7b4fbSAlexey Lapshin   *Iter++ = '\n';
23125d7b4fbSAlexey Lapshin   assert(Iter == Line.end());
23225d7b4fbSAlexey Lapshin   return Line;
23325d7b4fbSAlexey Lapshin }
23425d7b4fbSAlexey Lapshin 
checkRecord(const IHexRecord & R)23525d7b4fbSAlexey Lapshin static Error checkRecord(const IHexRecord &R) {
23625d7b4fbSAlexey Lapshin   switch (R.Type) {
23725d7b4fbSAlexey Lapshin   case IHexRecord::Data:
23825d7b4fbSAlexey Lapshin     if (R.HexData.size() == 0)
23925d7b4fbSAlexey Lapshin       return createStringError(
24025d7b4fbSAlexey Lapshin           errc::invalid_argument,
24125d7b4fbSAlexey Lapshin           "zero data length is not allowed for data records");
24225d7b4fbSAlexey Lapshin     break;
24325d7b4fbSAlexey Lapshin   case IHexRecord::EndOfFile:
24425d7b4fbSAlexey Lapshin     break;
24525d7b4fbSAlexey Lapshin   case IHexRecord::SegmentAddr:
24625d7b4fbSAlexey Lapshin     // 20-bit segment address. Data length must be 2 bytes
24725d7b4fbSAlexey Lapshin     // (4 bytes in hex)
24825d7b4fbSAlexey Lapshin     if (R.HexData.size() != 4)
24925d7b4fbSAlexey Lapshin       return createStringError(
25025d7b4fbSAlexey Lapshin           errc::invalid_argument,
25125d7b4fbSAlexey Lapshin           "segment address data should be 2 bytes in size");
25225d7b4fbSAlexey Lapshin     break;
25325d7b4fbSAlexey Lapshin   case IHexRecord::StartAddr80x86:
25425d7b4fbSAlexey Lapshin   case IHexRecord::StartAddr:
25525d7b4fbSAlexey Lapshin     if (R.HexData.size() != 8)
25625d7b4fbSAlexey Lapshin       return createStringError(errc::invalid_argument,
25725d7b4fbSAlexey Lapshin                                "start address data should be 4 bytes in size");
25825d7b4fbSAlexey Lapshin     // According to Intel HEX specification '03' record
25925d7b4fbSAlexey Lapshin     // only specifies the code address within the 20-bit
26025d7b4fbSAlexey Lapshin     // segmented address space of the 8086/80186. This
26125d7b4fbSAlexey Lapshin     // means 12 high order bits should be zeroes.
26225d7b4fbSAlexey Lapshin     if (R.Type == IHexRecord::StartAddr80x86 &&
26325d7b4fbSAlexey Lapshin         R.HexData.take_front(3) != "000")
26425d7b4fbSAlexey Lapshin       return createStringError(errc::invalid_argument,
26525d7b4fbSAlexey Lapshin                                "start address exceeds 20 bit for 80x86");
26625d7b4fbSAlexey Lapshin     break;
26725d7b4fbSAlexey Lapshin   case IHexRecord::ExtendedAddr:
26825d7b4fbSAlexey Lapshin     // 16-31 bits of linear base address
26925d7b4fbSAlexey Lapshin     if (R.HexData.size() != 4)
27025d7b4fbSAlexey Lapshin       return createStringError(
27125d7b4fbSAlexey Lapshin           errc::invalid_argument,
27225d7b4fbSAlexey Lapshin           "extended address data should be 2 bytes in size");
27325d7b4fbSAlexey Lapshin     break;
27425d7b4fbSAlexey Lapshin   default:
27525d7b4fbSAlexey Lapshin     // Unknown record type
27625d7b4fbSAlexey Lapshin     return createStringError(errc::invalid_argument, "unknown record type: %u",
27725d7b4fbSAlexey Lapshin                              static_cast<unsigned>(R.Type));
27825d7b4fbSAlexey Lapshin   }
27925d7b4fbSAlexey Lapshin   return Error::success();
28025d7b4fbSAlexey Lapshin }
28125d7b4fbSAlexey Lapshin 
28225d7b4fbSAlexey Lapshin // Checks that IHEX line contains valid characters.
28325d7b4fbSAlexey Lapshin // This allows converting hexadecimal data to integers
28425d7b4fbSAlexey Lapshin // without extra verification.
checkChars(StringRef Line)28525d7b4fbSAlexey Lapshin static Error checkChars(StringRef Line) {
28625d7b4fbSAlexey Lapshin   assert(!Line.empty());
28725d7b4fbSAlexey Lapshin   if (Line[0] != ':')
28825d7b4fbSAlexey Lapshin     return createStringError(errc::invalid_argument,
28925d7b4fbSAlexey Lapshin                              "missing ':' in the beginning of line.");
29025d7b4fbSAlexey Lapshin 
29125d7b4fbSAlexey Lapshin   for (size_t Pos = 1; Pos < Line.size(); ++Pos)
29225d7b4fbSAlexey Lapshin     if (hexDigitValue(Line[Pos]) == -1U)
29325d7b4fbSAlexey Lapshin       return createStringError(errc::invalid_argument,
29425d7b4fbSAlexey Lapshin                                "invalid character at position %zu.", Pos + 1);
29525d7b4fbSAlexey Lapshin   return Error::success();
29625d7b4fbSAlexey Lapshin }
29725d7b4fbSAlexey Lapshin 
parse(StringRef Line)29825d7b4fbSAlexey Lapshin Expected<IHexRecord> IHexRecord::parse(StringRef Line) {
29925d7b4fbSAlexey Lapshin   assert(!Line.empty());
30025d7b4fbSAlexey Lapshin 
30125d7b4fbSAlexey Lapshin   // ':' + Length + Address + Type + Checksum with empty data ':LLAAAATTCC'
30225d7b4fbSAlexey Lapshin   if (Line.size() < 11)
30325d7b4fbSAlexey Lapshin     return createStringError(errc::invalid_argument,
30425d7b4fbSAlexey Lapshin                              "line is too short: %zu chars.", Line.size());
30525d7b4fbSAlexey Lapshin 
30625d7b4fbSAlexey Lapshin   if (Error E = checkChars(Line))
30725d7b4fbSAlexey Lapshin     return std::move(E);
30825d7b4fbSAlexey Lapshin 
30925d7b4fbSAlexey Lapshin   IHexRecord Rec;
31025d7b4fbSAlexey Lapshin   size_t DataLen = checkedGetHex<uint8_t>(Line.substr(1, 2));
31125d7b4fbSAlexey Lapshin   if (Line.size() != getLength(DataLen))
31225d7b4fbSAlexey Lapshin     return createStringError(errc::invalid_argument,
31325d7b4fbSAlexey Lapshin                              "invalid line length %zu (should be %zu)",
31425d7b4fbSAlexey Lapshin                              Line.size(), getLength(DataLen));
31525d7b4fbSAlexey Lapshin 
31625d7b4fbSAlexey Lapshin   Rec.Addr = checkedGetHex<uint16_t>(Line.substr(3, 4));
31725d7b4fbSAlexey Lapshin   Rec.Type = checkedGetHex<uint8_t>(Line.substr(7, 2));
31825d7b4fbSAlexey Lapshin   Rec.HexData = Line.substr(9, DataLen * 2);
31925d7b4fbSAlexey Lapshin 
32025d7b4fbSAlexey Lapshin   if (getChecksum(Line.drop_front(1)) != 0)
32125d7b4fbSAlexey Lapshin     return createStringError(errc::invalid_argument, "incorrect checksum.");
32225d7b4fbSAlexey Lapshin   if (Error E = checkRecord(Rec))
32325d7b4fbSAlexey Lapshin     return std::move(E);
32425d7b4fbSAlexey Lapshin   return Rec;
32525d7b4fbSAlexey Lapshin }
32625d7b4fbSAlexey Lapshin 
sectionPhysicalAddr(const SectionBase * Sec)32725d7b4fbSAlexey Lapshin static uint64_t sectionPhysicalAddr(const SectionBase *Sec) {
32825d7b4fbSAlexey Lapshin   Segment *Seg = Sec->ParentSegment;
32925d7b4fbSAlexey Lapshin   if (Seg && Seg->Type != ELF::PT_LOAD)
33025d7b4fbSAlexey Lapshin     Seg = nullptr;
33125d7b4fbSAlexey Lapshin   return Seg ? Seg->PAddr + Sec->OriginalOffset - Seg->OriginalOffset
33225d7b4fbSAlexey Lapshin              : Sec->Addr;
33325d7b4fbSAlexey Lapshin }
33425d7b4fbSAlexey Lapshin 
writeSection(const SectionBase * Sec,ArrayRef<uint8_t> Data)33525d7b4fbSAlexey Lapshin void IHexSectionWriterBase::writeSection(const SectionBase *Sec,
33625d7b4fbSAlexey Lapshin                                          ArrayRef<uint8_t> Data) {
33725d7b4fbSAlexey Lapshin   assert(Data.size() == Sec->Size);
33825d7b4fbSAlexey Lapshin   const uint32_t ChunkSize = 16;
33925d7b4fbSAlexey Lapshin   uint32_t Addr = sectionPhysicalAddr(Sec) & 0xFFFFFFFFU;
34025d7b4fbSAlexey Lapshin   while (!Data.empty()) {
34125d7b4fbSAlexey Lapshin     uint64_t DataSize = std::min<uint64_t>(Data.size(), ChunkSize);
34225d7b4fbSAlexey Lapshin     if (Addr > SegmentAddr + BaseAddr + 0xFFFFU) {
34325d7b4fbSAlexey Lapshin       if (Addr > 0xFFFFFU) {
34425d7b4fbSAlexey Lapshin         // Write extended address record, zeroing segment address
34525d7b4fbSAlexey Lapshin         // if needed.
34625d7b4fbSAlexey Lapshin         if (SegmentAddr != 0)
34725d7b4fbSAlexey Lapshin           SegmentAddr = writeSegmentAddr(0U);
34825d7b4fbSAlexey Lapshin         BaseAddr = writeBaseAddr(Addr);
34925d7b4fbSAlexey Lapshin       } else {
35025d7b4fbSAlexey Lapshin         // We can still remain 16-bit
35125d7b4fbSAlexey Lapshin         SegmentAddr = writeSegmentAddr(Addr);
35225d7b4fbSAlexey Lapshin       }
35325d7b4fbSAlexey Lapshin     }
35425d7b4fbSAlexey Lapshin     uint64_t SegOffset = Addr - BaseAddr - SegmentAddr;
35525d7b4fbSAlexey Lapshin     assert(SegOffset <= 0xFFFFU);
35625d7b4fbSAlexey Lapshin     DataSize = std::min(DataSize, 0x10000U - SegOffset);
35725d7b4fbSAlexey Lapshin     writeData(0, SegOffset, Data.take_front(DataSize));
35825d7b4fbSAlexey Lapshin     Addr += DataSize;
35925d7b4fbSAlexey Lapshin     Data = Data.drop_front(DataSize);
36025d7b4fbSAlexey Lapshin   }
36125d7b4fbSAlexey Lapshin }
36225d7b4fbSAlexey Lapshin 
writeSegmentAddr(uint64_t Addr)36325d7b4fbSAlexey Lapshin uint64_t IHexSectionWriterBase::writeSegmentAddr(uint64_t Addr) {
36425d7b4fbSAlexey Lapshin   assert(Addr <= 0xFFFFFU);
36525d7b4fbSAlexey Lapshin   uint8_t Data[] = {static_cast<uint8_t>((Addr & 0xF0000U) >> 12), 0};
36625d7b4fbSAlexey Lapshin   writeData(2, 0, Data);
36725d7b4fbSAlexey Lapshin   return Addr & 0xF0000U;
36825d7b4fbSAlexey Lapshin }
36925d7b4fbSAlexey Lapshin 
writeBaseAddr(uint64_t Addr)37025d7b4fbSAlexey Lapshin uint64_t IHexSectionWriterBase::writeBaseAddr(uint64_t Addr) {
37125d7b4fbSAlexey Lapshin   assert(Addr <= 0xFFFFFFFFU);
37225d7b4fbSAlexey Lapshin   uint64_t Base = Addr & 0xFFFF0000U;
37325d7b4fbSAlexey Lapshin   uint8_t Data[] = {static_cast<uint8_t>(Base >> 24),
37425d7b4fbSAlexey Lapshin                     static_cast<uint8_t>((Base >> 16) & 0xFF)};
37525d7b4fbSAlexey Lapshin   writeData(4, 0, Data);
37625d7b4fbSAlexey Lapshin   return Base;
37725d7b4fbSAlexey Lapshin }
37825d7b4fbSAlexey Lapshin 
writeData(uint8_t,uint16_t,ArrayRef<uint8_t> Data)37925d7b4fbSAlexey Lapshin void IHexSectionWriterBase::writeData(uint8_t, uint16_t,
38025d7b4fbSAlexey Lapshin                                       ArrayRef<uint8_t> Data) {
38125d7b4fbSAlexey Lapshin   Offset += IHexRecord::getLineLength(Data.size());
38225d7b4fbSAlexey Lapshin }
38325d7b4fbSAlexey Lapshin 
visit(const Section & Sec)38425d7b4fbSAlexey Lapshin Error IHexSectionWriterBase::visit(const Section &Sec) {
38525d7b4fbSAlexey Lapshin   writeSection(&Sec, Sec.Contents);
38625d7b4fbSAlexey Lapshin   return Error::success();
38725d7b4fbSAlexey Lapshin }
38825d7b4fbSAlexey Lapshin 
visit(const OwnedDataSection & Sec)38925d7b4fbSAlexey Lapshin Error IHexSectionWriterBase::visit(const OwnedDataSection &Sec) {
39025d7b4fbSAlexey Lapshin   writeSection(&Sec, Sec.Data);
39125d7b4fbSAlexey Lapshin   return Error::success();
39225d7b4fbSAlexey Lapshin }
39325d7b4fbSAlexey Lapshin 
visit(const StringTableSection & Sec)39425d7b4fbSAlexey Lapshin Error IHexSectionWriterBase::visit(const StringTableSection &Sec) {
39525d7b4fbSAlexey Lapshin   // Check that sizer has already done its work
39625d7b4fbSAlexey Lapshin   assert(Sec.Size == Sec.StrTabBuilder.getSize());
39725d7b4fbSAlexey Lapshin   // We are free to pass an invalid pointer to writeSection as long
39825d7b4fbSAlexey Lapshin   // as we don't actually write any data. The real writer class has
39925d7b4fbSAlexey Lapshin   // to override this method .
40025d7b4fbSAlexey Lapshin   writeSection(&Sec, {nullptr, static_cast<size_t>(Sec.Size)});
40125d7b4fbSAlexey Lapshin   return Error::success();
40225d7b4fbSAlexey Lapshin }
40325d7b4fbSAlexey Lapshin 
visit(const DynamicRelocationSection & Sec)40425d7b4fbSAlexey Lapshin Error IHexSectionWriterBase::visit(const DynamicRelocationSection &Sec) {
40525d7b4fbSAlexey Lapshin   writeSection(&Sec, Sec.Contents);
40625d7b4fbSAlexey Lapshin   return Error::success();
40725d7b4fbSAlexey Lapshin }
40825d7b4fbSAlexey Lapshin 
writeData(uint8_t Type,uint16_t Addr,ArrayRef<uint8_t> Data)40925d7b4fbSAlexey Lapshin void IHexSectionWriter::writeData(uint8_t Type, uint16_t Addr,
41025d7b4fbSAlexey Lapshin                                   ArrayRef<uint8_t> Data) {
41125d7b4fbSAlexey Lapshin   IHexLineData HexData = IHexRecord::getLine(Type, Addr, Data);
41225d7b4fbSAlexey Lapshin   memcpy(Out.getBufferStart() + Offset, HexData.data(), HexData.size());
41325d7b4fbSAlexey Lapshin   Offset += HexData.size();
41425d7b4fbSAlexey Lapshin }
41525d7b4fbSAlexey Lapshin 
visit(const StringTableSection & Sec)41625d7b4fbSAlexey Lapshin Error IHexSectionWriter::visit(const StringTableSection &Sec) {
41725d7b4fbSAlexey Lapshin   assert(Sec.Size == Sec.StrTabBuilder.getSize());
41825d7b4fbSAlexey Lapshin   std::vector<uint8_t> Data(Sec.Size);
41925d7b4fbSAlexey Lapshin   Sec.StrTabBuilder.write(Data.data());
42025d7b4fbSAlexey Lapshin   writeSection(&Sec, Data);
42125d7b4fbSAlexey Lapshin   return Error::success();
42225d7b4fbSAlexey Lapshin }
42325d7b4fbSAlexey Lapshin 
accept(SectionVisitor & Visitor) const42425d7b4fbSAlexey Lapshin Error Section::accept(SectionVisitor &Visitor) const {
42525d7b4fbSAlexey Lapshin   return Visitor.visit(*this);
42625d7b4fbSAlexey Lapshin }
42725d7b4fbSAlexey Lapshin 
accept(MutableSectionVisitor & Visitor)42825d7b4fbSAlexey Lapshin Error Section::accept(MutableSectionVisitor &Visitor) {
42925d7b4fbSAlexey Lapshin   return Visitor.visit(*this);
43025d7b4fbSAlexey Lapshin }
43125d7b4fbSAlexey Lapshin 
visit(const OwnedDataSection & Sec)43225d7b4fbSAlexey Lapshin Error SectionWriter::visit(const OwnedDataSection &Sec) {
43325d7b4fbSAlexey Lapshin   llvm::copy(Sec.Data, Out.getBufferStart() + Sec.Offset);
43425d7b4fbSAlexey Lapshin   return Error::success();
43525d7b4fbSAlexey Lapshin }
43625d7b4fbSAlexey Lapshin 
43725d7b4fbSAlexey Lapshin template <class ELFT>
visit(const DecompressedSection & Sec)43825d7b4fbSAlexey Lapshin Error ELFSectionWriter<ELFT>::visit(const DecompressedSection &Sec) {
43973c84f9cSFangrui Song   ArrayRef<uint8_t> Compressed =
44073c84f9cSFangrui Song       Sec.OriginalData.slice(sizeof(Elf_Chdr_Impl<ELFT>));
441e690137dSFangrui Song   SmallVector<uint8_t, 128> DecompressedContent;
44273c84f9cSFangrui Song   if (Error Err = compression::zlib::uncompress(Compressed, DecompressedContent,
44325d7b4fbSAlexey Lapshin                                                 static_cast<size_t>(Sec.Size)))
44425d7b4fbSAlexey Lapshin     return createStringError(errc::invalid_argument,
44525d7b4fbSAlexey Lapshin                              "'" + Sec.Name + "': " + toString(std::move(Err)));
44625d7b4fbSAlexey Lapshin 
44725d7b4fbSAlexey Lapshin   uint8_t *Buf = reinterpret_cast<uint8_t *>(Out.getBufferStart()) + Sec.Offset;
44825d7b4fbSAlexey Lapshin   std::copy(DecompressedContent.begin(), DecompressedContent.end(), Buf);
44925d7b4fbSAlexey Lapshin 
45025d7b4fbSAlexey Lapshin   return Error::success();
45125d7b4fbSAlexey Lapshin }
45225d7b4fbSAlexey Lapshin 
visit(const DecompressedSection & Sec)45325d7b4fbSAlexey Lapshin Error BinarySectionWriter::visit(const DecompressedSection &Sec) {
45425d7b4fbSAlexey Lapshin   return createStringError(errc::operation_not_permitted,
45525d7b4fbSAlexey Lapshin                            "cannot write compressed section '" + Sec.Name +
45625d7b4fbSAlexey Lapshin                                "' ");
45725d7b4fbSAlexey Lapshin }
45825d7b4fbSAlexey Lapshin 
accept(SectionVisitor & Visitor) const45925d7b4fbSAlexey Lapshin Error DecompressedSection::accept(SectionVisitor &Visitor) const {
46025d7b4fbSAlexey Lapshin   return Visitor.visit(*this);
46125d7b4fbSAlexey Lapshin }
46225d7b4fbSAlexey Lapshin 
accept(MutableSectionVisitor & Visitor)46325d7b4fbSAlexey Lapshin Error DecompressedSection::accept(MutableSectionVisitor &Visitor) {
46425d7b4fbSAlexey Lapshin   return Visitor.visit(*this);
46525d7b4fbSAlexey Lapshin }
46625d7b4fbSAlexey Lapshin 
accept(SectionVisitor & Visitor) const46725d7b4fbSAlexey Lapshin Error OwnedDataSection::accept(SectionVisitor &Visitor) const {
46825d7b4fbSAlexey Lapshin   return Visitor.visit(*this);
46925d7b4fbSAlexey Lapshin }
47025d7b4fbSAlexey Lapshin 
accept(MutableSectionVisitor & Visitor)47125d7b4fbSAlexey Lapshin Error OwnedDataSection::accept(MutableSectionVisitor &Visitor) {
47225d7b4fbSAlexey Lapshin   return Visitor.visit(*this);
47325d7b4fbSAlexey Lapshin }
47425d7b4fbSAlexey Lapshin 
appendHexData(StringRef HexData)47525d7b4fbSAlexey Lapshin void OwnedDataSection::appendHexData(StringRef HexData) {
47625d7b4fbSAlexey Lapshin   assert((HexData.size() & 1) == 0);
47725d7b4fbSAlexey Lapshin   while (!HexData.empty()) {
47825d7b4fbSAlexey Lapshin     Data.push_back(checkedGetHex<uint8_t>(HexData.take_front(2)));
47925d7b4fbSAlexey Lapshin     HexData = HexData.drop_front(2);
48025d7b4fbSAlexey Lapshin   }
48125d7b4fbSAlexey Lapshin   Size = Data.size();
48225d7b4fbSAlexey Lapshin }
48325d7b4fbSAlexey Lapshin 
visit(const CompressedSection & Sec)48425d7b4fbSAlexey Lapshin Error BinarySectionWriter::visit(const CompressedSection &Sec) {
48525d7b4fbSAlexey Lapshin   return createStringError(errc::operation_not_permitted,
48625d7b4fbSAlexey Lapshin                            "cannot write compressed section '" + Sec.Name +
48725d7b4fbSAlexey Lapshin                                "' ");
48825d7b4fbSAlexey Lapshin }
48925d7b4fbSAlexey Lapshin 
49025d7b4fbSAlexey Lapshin template <class ELFT>
visit(const CompressedSection & Sec)49125d7b4fbSAlexey Lapshin Error ELFSectionWriter<ELFT>::visit(const CompressedSection &Sec) {
49225d7b4fbSAlexey Lapshin   uint8_t *Buf = reinterpret_cast<uint8_t *>(Out.getBufferStart()) + Sec.Offset;
4937181c4e1SFangrui Song   Elf_Chdr_Impl<ELFT> Chdr = {};
49445ae5531SFangrui Song   switch (Sec.CompressionType) {
49545ae5531SFangrui Song   case DebugCompressionType::None:
49625d7b4fbSAlexey Lapshin     std::copy(Sec.OriginalData.begin(), Sec.OriginalData.end(), Buf);
49725d7b4fbSAlexey Lapshin     return Error::success();
49845ae5531SFangrui Song   case DebugCompressionType::Z:
49925d7b4fbSAlexey Lapshin     Chdr.ch_type = ELF::ELFCOMPRESS_ZLIB;
50045ae5531SFangrui Song     break;
50145ae5531SFangrui Song   }
50225d7b4fbSAlexey Lapshin   Chdr.ch_size = Sec.DecompressedSize;
50325d7b4fbSAlexey Lapshin   Chdr.ch_addralign = Sec.DecompressedAlign;
50425d7b4fbSAlexey Lapshin   memcpy(Buf, &Chdr, sizeof(Chdr));
50525d7b4fbSAlexey Lapshin   Buf += sizeof(Chdr);
50625d7b4fbSAlexey Lapshin 
50725d7b4fbSAlexey Lapshin   std::copy(Sec.CompressedData.begin(), Sec.CompressedData.end(), Buf);
50825d7b4fbSAlexey Lapshin   return Error::success();
50925d7b4fbSAlexey Lapshin }
51025d7b4fbSAlexey Lapshin 
CompressedSection(const SectionBase & Sec,DebugCompressionType CompressionType)51125d7b4fbSAlexey Lapshin CompressedSection::CompressedSection(const SectionBase &Sec,
512407c721cSFangrui Song                                      DebugCompressionType CompressionType)
51325d7b4fbSAlexey Lapshin     : SectionBase(Sec), CompressionType(CompressionType),
51425d7b4fbSAlexey Lapshin       DecompressedSize(Sec.OriginalData.size()), DecompressedAlign(Sec.Align) {
515e690137dSFangrui Song   compression::zlib::compress(OriginalData, CompressedData);
51625d7b4fbSAlexey Lapshin 
51745ae5531SFangrui Song   assert(CompressionType != DebugCompressionType::None);
51825d7b4fbSAlexey Lapshin   Flags |= ELF::SHF_COMPRESSED;
51945ae5531SFangrui Song   size_t ChdrSize =
52025d7b4fbSAlexey Lapshin       std::max(std::max(sizeof(object::Elf_Chdr_Impl<object::ELF64LE>),
52125d7b4fbSAlexey Lapshin                         sizeof(object::Elf_Chdr_Impl<object::ELF64BE>)),
52225d7b4fbSAlexey Lapshin                std::max(sizeof(object::Elf_Chdr_Impl<object::ELF32LE>),
52325d7b4fbSAlexey Lapshin                         sizeof(object::Elf_Chdr_Impl<object::ELF32BE>)));
52425d7b4fbSAlexey Lapshin   Size = ChdrSize + CompressedData.size();
52525d7b4fbSAlexey Lapshin   Align = 8;
52625d7b4fbSAlexey Lapshin }
52725d7b4fbSAlexey Lapshin 
CompressedSection(ArrayRef<uint8_t> CompressedData,uint64_t DecompressedSize,uint64_t DecompressedAlign)52825d7b4fbSAlexey Lapshin CompressedSection::CompressedSection(ArrayRef<uint8_t> CompressedData,
52925d7b4fbSAlexey Lapshin                                      uint64_t DecompressedSize,
53025d7b4fbSAlexey Lapshin                                      uint64_t DecompressedAlign)
53125d7b4fbSAlexey Lapshin     : CompressionType(DebugCompressionType::None),
53225d7b4fbSAlexey Lapshin       DecompressedSize(DecompressedSize), DecompressedAlign(DecompressedAlign) {
53325d7b4fbSAlexey Lapshin   OriginalData = CompressedData;
53425d7b4fbSAlexey Lapshin }
53525d7b4fbSAlexey Lapshin 
accept(SectionVisitor & Visitor) const53625d7b4fbSAlexey Lapshin Error CompressedSection::accept(SectionVisitor &Visitor) const {
53725d7b4fbSAlexey Lapshin   return Visitor.visit(*this);
53825d7b4fbSAlexey Lapshin }
53925d7b4fbSAlexey Lapshin 
accept(MutableSectionVisitor & Visitor)54025d7b4fbSAlexey Lapshin Error CompressedSection::accept(MutableSectionVisitor &Visitor) {
54125d7b4fbSAlexey Lapshin   return Visitor.visit(*this);
54225d7b4fbSAlexey Lapshin }
54325d7b4fbSAlexey Lapshin 
addString(StringRef Name)54425d7b4fbSAlexey Lapshin void StringTableSection::addString(StringRef Name) { StrTabBuilder.add(Name); }
54525d7b4fbSAlexey Lapshin 
findIndex(StringRef Name) const54625d7b4fbSAlexey Lapshin uint32_t StringTableSection::findIndex(StringRef Name) const {
54725d7b4fbSAlexey Lapshin   return StrTabBuilder.getOffset(Name);
54825d7b4fbSAlexey Lapshin }
54925d7b4fbSAlexey Lapshin 
prepareForLayout()55025d7b4fbSAlexey Lapshin void StringTableSection::prepareForLayout() {
55125d7b4fbSAlexey Lapshin   StrTabBuilder.finalize();
55225d7b4fbSAlexey Lapshin   Size = StrTabBuilder.getSize();
55325d7b4fbSAlexey Lapshin }
55425d7b4fbSAlexey Lapshin 
visit(const StringTableSection & Sec)55525d7b4fbSAlexey Lapshin Error SectionWriter::visit(const StringTableSection &Sec) {
55625d7b4fbSAlexey Lapshin   Sec.StrTabBuilder.write(reinterpret_cast<uint8_t *>(Out.getBufferStart()) +
55725d7b4fbSAlexey Lapshin                           Sec.Offset);
55825d7b4fbSAlexey Lapshin   return Error::success();
55925d7b4fbSAlexey Lapshin }
56025d7b4fbSAlexey Lapshin 
accept(SectionVisitor & Visitor) const56125d7b4fbSAlexey Lapshin Error StringTableSection::accept(SectionVisitor &Visitor) const {
56225d7b4fbSAlexey Lapshin   return Visitor.visit(*this);
56325d7b4fbSAlexey Lapshin }
56425d7b4fbSAlexey Lapshin 
accept(MutableSectionVisitor & Visitor)56525d7b4fbSAlexey Lapshin Error StringTableSection::accept(MutableSectionVisitor &Visitor) {
56625d7b4fbSAlexey Lapshin   return Visitor.visit(*this);
56725d7b4fbSAlexey Lapshin }
56825d7b4fbSAlexey Lapshin 
56925d7b4fbSAlexey Lapshin template <class ELFT>
visit(const SectionIndexSection & Sec)57025d7b4fbSAlexey Lapshin Error ELFSectionWriter<ELFT>::visit(const SectionIndexSection &Sec) {
57125d7b4fbSAlexey Lapshin   uint8_t *Buf = reinterpret_cast<uint8_t *>(Out.getBufferStart()) + Sec.Offset;
57225d7b4fbSAlexey Lapshin   llvm::copy(Sec.Indexes, reinterpret_cast<Elf_Word *>(Buf));
57325d7b4fbSAlexey Lapshin   return Error::success();
57425d7b4fbSAlexey Lapshin }
57525d7b4fbSAlexey Lapshin 
initialize(SectionTableRef SecTable)57625d7b4fbSAlexey Lapshin Error SectionIndexSection::initialize(SectionTableRef SecTable) {
57725d7b4fbSAlexey Lapshin   Size = 0;
57825d7b4fbSAlexey Lapshin   Expected<SymbolTableSection *> Sec =
57925d7b4fbSAlexey Lapshin       SecTable.getSectionOfType<SymbolTableSection>(
58025d7b4fbSAlexey Lapshin           Link,
58125d7b4fbSAlexey Lapshin           "Link field value " + Twine(Link) + " in section " + Name +
58225d7b4fbSAlexey Lapshin               " is invalid",
58325d7b4fbSAlexey Lapshin           "Link field value " + Twine(Link) + " in section " + Name +
58425d7b4fbSAlexey Lapshin               " is not a symbol table");
58525d7b4fbSAlexey Lapshin   if (!Sec)
58625d7b4fbSAlexey Lapshin     return Sec.takeError();
58725d7b4fbSAlexey Lapshin 
58825d7b4fbSAlexey Lapshin   setSymTab(*Sec);
58925d7b4fbSAlexey Lapshin   Symbols->setShndxTable(this);
59025d7b4fbSAlexey Lapshin   return Error::success();
59125d7b4fbSAlexey Lapshin }
59225d7b4fbSAlexey Lapshin 
finalize()59325d7b4fbSAlexey Lapshin void SectionIndexSection::finalize() { Link = Symbols->Index; }
59425d7b4fbSAlexey Lapshin 
accept(SectionVisitor & Visitor) const59525d7b4fbSAlexey Lapshin Error SectionIndexSection::accept(SectionVisitor &Visitor) const {
59625d7b4fbSAlexey Lapshin   return Visitor.visit(*this);
59725d7b4fbSAlexey Lapshin }
59825d7b4fbSAlexey Lapshin 
accept(MutableSectionVisitor & Visitor)59925d7b4fbSAlexey Lapshin Error SectionIndexSection::accept(MutableSectionVisitor &Visitor) {
60025d7b4fbSAlexey Lapshin   return Visitor.visit(*this);
60125d7b4fbSAlexey Lapshin }
60225d7b4fbSAlexey Lapshin 
isValidReservedSectionIndex(uint16_t Index,uint16_t Machine)60325d7b4fbSAlexey Lapshin static bool isValidReservedSectionIndex(uint16_t Index, uint16_t Machine) {
60425d7b4fbSAlexey Lapshin   switch (Index) {
60525d7b4fbSAlexey Lapshin   case SHN_ABS:
60625d7b4fbSAlexey Lapshin   case SHN_COMMON:
60725d7b4fbSAlexey Lapshin     return true;
60825d7b4fbSAlexey Lapshin   }
60925d7b4fbSAlexey Lapshin 
61025d7b4fbSAlexey Lapshin   if (Machine == EM_AMDGPU) {
61125d7b4fbSAlexey Lapshin     return Index == SHN_AMDGPU_LDS;
61225d7b4fbSAlexey Lapshin   }
61325d7b4fbSAlexey Lapshin 
6149da89651SAnubhab Ghosh   if (Machine == EM_MIPS) {
6159da89651SAnubhab Ghosh     switch (Index) {
6169da89651SAnubhab Ghosh     case SHN_MIPS_ACOMMON:
6179da89651SAnubhab Ghosh     case SHN_MIPS_SCOMMON:
6189da89651SAnubhab Ghosh     case SHN_MIPS_SUNDEFINED:
6199da89651SAnubhab Ghosh       return true;
6209da89651SAnubhab Ghosh     }
6219da89651SAnubhab Ghosh   }
6229da89651SAnubhab Ghosh 
62325d7b4fbSAlexey Lapshin   if (Machine == EM_HEXAGON) {
62425d7b4fbSAlexey Lapshin     switch (Index) {
62525d7b4fbSAlexey Lapshin     case SHN_HEXAGON_SCOMMON:
62625d7b4fbSAlexey Lapshin     case SHN_HEXAGON_SCOMMON_1:
62725d7b4fbSAlexey Lapshin     case SHN_HEXAGON_SCOMMON_2:
62825d7b4fbSAlexey Lapshin     case SHN_HEXAGON_SCOMMON_4:
62925d7b4fbSAlexey Lapshin     case SHN_HEXAGON_SCOMMON_8:
63025d7b4fbSAlexey Lapshin       return true;
63125d7b4fbSAlexey Lapshin     }
63225d7b4fbSAlexey Lapshin   }
63325d7b4fbSAlexey Lapshin   return false;
63425d7b4fbSAlexey Lapshin }
63525d7b4fbSAlexey Lapshin 
63625d7b4fbSAlexey Lapshin // Large indexes force us to clarify exactly what this function should do. This
63725d7b4fbSAlexey Lapshin // function should return the value that will appear in st_shndx when written
63825d7b4fbSAlexey Lapshin // out.
getShndx() const63925d7b4fbSAlexey Lapshin uint16_t Symbol::getShndx() const {
64025d7b4fbSAlexey Lapshin   if (DefinedIn != nullptr) {
64125d7b4fbSAlexey Lapshin     if (DefinedIn->Index >= SHN_LORESERVE)
64225d7b4fbSAlexey Lapshin       return SHN_XINDEX;
64325d7b4fbSAlexey Lapshin     return DefinedIn->Index;
64425d7b4fbSAlexey Lapshin   }
64525d7b4fbSAlexey Lapshin 
64625d7b4fbSAlexey Lapshin   if (ShndxType == SYMBOL_SIMPLE_INDEX) {
64725d7b4fbSAlexey Lapshin     // This means that we don't have a defined section but we do need to
64825d7b4fbSAlexey Lapshin     // output a legitimate section index.
64925d7b4fbSAlexey Lapshin     return SHN_UNDEF;
65025d7b4fbSAlexey Lapshin   }
65125d7b4fbSAlexey Lapshin 
65225d7b4fbSAlexey Lapshin   assert(ShndxType == SYMBOL_ABS || ShndxType == SYMBOL_COMMON ||
65325d7b4fbSAlexey Lapshin          (ShndxType >= SYMBOL_LOPROC && ShndxType <= SYMBOL_HIPROC) ||
65425d7b4fbSAlexey Lapshin          (ShndxType >= SYMBOL_LOOS && ShndxType <= SYMBOL_HIOS));
65525d7b4fbSAlexey Lapshin   return static_cast<uint16_t>(ShndxType);
65625d7b4fbSAlexey Lapshin }
65725d7b4fbSAlexey Lapshin 
isCommon() const65825d7b4fbSAlexey Lapshin bool Symbol::isCommon() const { return getShndx() == SHN_COMMON; }
65925d7b4fbSAlexey Lapshin 
assignIndices()66025d7b4fbSAlexey Lapshin void SymbolTableSection::assignIndices() {
66125d7b4fbSAlexey Lapshin   uint32_t Index = 0;
66225d7b4fbSAlexey Lapshin   for (auto &Sym : Symbols)
66325d7b4fbSAlexey Lapshin     Sym->Index = Index++;
66425d7b4fbSAlexey Lapshin }
66525d7b4fbSAlexey Lapshin 
addSymbol(Twine Name,uint8_t Bind,uint8_t Type,SectionBase * DefinedIn,uint64_t Value,uint8_t Visibility,uint16_t Shndx,uint64_t SymbolSize)66625d7b4fbSAlexey Lapshin void SymbolTableSection::addSymbol(Twine Name, uint8_t Bind, uint8_t Type,
66725d7b4fbSAlexey Lapshin                                    SectionBase *DefinedIn, uint64_t Value,
66825d7b4fbSAlexey Lapshin                                    uint8_t Visibility, uint16_t Shndx,
66925d7b4fbSAlexey Lapshin                                    uint64_t SymbolSize) {
67025d7b4fbSAlexey Lapshin   Symbol Sym;
67125d7b4fbSAlexey Lapshin   Sym.Name = Name.str();
67225d7b4fbSAlexey Lapshin   Sym.Binding = Bind;
67325d7b4fbSAlexey Lapshin   Sym.Type = Type;
67425d7b4fbSAlexey Lapshin   Sym.DefinedIn = DefinedIn;
67525d7b4fbSAlexey Lapshin   if (DefinedIn != nullptr)
67625d7b4fbSAlexey Lapshin     DefinedIn->HasSymbol = true;
67725d7b4fbSAlexey Lapshin   if (DefinedIn == nullptr) {
67825d7b4fbSAlexey Lapshin     if (Shndx >= SHN_LORESERVE)
67925d7b4fbSAlexey Lapshin       Sym.ShndxType = static_cast<SymbolShndxType>(Shndx);
68025d7b4fbSAlexey Lapshin     else
68125d7b4fbSAlexey Lapshin       Sym.ShndxType = SYMBOL_SIMPLE_INDEX;
68225d7b4fbSAlexey Lapshin   }
68325d7b4fbSAlexey Lapshin   Sym.Value = Value;
68425d7b4fbSAlexey Lapshin   Sym.Visibility = Visibility;
68525d7b4fbSAlexey Lapshin   Sym.Size = SymbolSize;
68625d7b4fbSAlexey Lapshin   Sym.Index = Symbols.size();
68725d7b4fbSAlexey Lapshin   Symbols.emplace_back(std::make_unique<Symbol>(Sym));
68825d7b4fbSAlexey Lapshin   Size += this->EntrySize;
68925d7b4fbSAlexey Lapshin }
69025d7b4fbSAlexey Lapshin 
removeSectionReferences(bool AllowBrokenLinks,function_ref<bool (const SectionBase *)> ToRemove)69125d7b4fbSAlexey Lapshin Error SymbolTableSection::removeSectionReferences(
69225d7b4fbSAlexey Lapshin     bool AllowBrokenLinks, function_ref<bool(const SectionBase *)> ToRemove) {
69325d7b4fbSAlexey Lapshin   if (ToRemove(SectionIndexTable))
69425d7b4fbSAlexey Lapshin     SectionIndexTable = nullptr;
69525d7b4fbSAlexey Lapshin   if (ToRemove(SymbolNames)) {
69625d7b4fbSAlexey Lapshin     if (!AllowBrokenLinks)
69725d7b4fbSAlexey Lapshin       return createStringError(
69825d7b4fbSAlexey Lapshin           llvm::errc::invalid_argument,
69925d7b4fbSAlexey Lapshin           "string table '%s' cannot be removed because it is "
70025d7b4fbSAlexey Lapshin           "referenced by the symbol table '%s'",
70125d7b4fbSAlexey Lapshin           SymbolNames->Name.data(), this->Name.data());
70225d7b4fbSAlexey Lapshin     SymbolNames = nullptr;
70325d7b4fbSAlexey Lapshin   }
70425d7b4fbSAlexey Lapshin   return removeSymbols(
70525d7b4fbSAlexey Lapshin       [ToRemove](const Symbol &Sym) { return ToRemove(Sym.DefinedIn); });
70625d7b4fbSAlexey Lapshin }
70725d7b4fbSAlexey Lapshin 
updateSymbols(function_ref<void (Symbol &)> Callable)70825d7b4fbSAlexey Lapshin void SymbolTableSection::updateSymbols(function_ref<void(Symbol &)> Callable) {
7093b9707dbSKazu Hirata   for (SymPtr &Sym : llvm::drop_begin(Symbols))
7103b9707dbSKazu Hirata     Callable(*Sym);
71125d7b4fbSAlexey Lapshin   std::stable_partition(
71225d7b4fbSAlexey Lapshin       std::begin(Symbols), std::end(Symbols),
71325d7b4fbSAlexey Lapshin       [](const SymPtr &Sym) { return Sym->Binding == STB_LOCAL; });
71425d7b4fbSAlexey Lapshin   assignIndices();
71525d7b4fbSAlexey Lapshin }
71625d7b4fbSAlexey Lapshin 
removeSymbols(function_ref<bool (const Symbol &)> ToRemove)71725d7b4fbSAlexey Lapshin Error SymbolTableSection::removeSymbols(
71825d7b4fbSAlexey Lapshin     function_ref<bool(const Symbol &)> ToRemove) {
71925d7b4fbSAlexey Lapshin   Symbols.erase(
72025d7b4fbSAlexey Lapshin       std::remove_if(std::begin(Symbols) + 1, std::end(Symbols),
72125d7b4fbSAlexey Lapshin                      [ToRemove](const SymPtr &Sym) { return ToRemove(*Sym); }),
72225d7b4fbSAlexey Lapshin       std::end(Symbols));
72325d7b4fbSAlexey Lapshin   Size = Symbols.size() * EntrySize;
72425d7b4fbSAlexey Lapshin   assignIndices();
72525d7b4fbSAlexey Lapshin   return Error::success();
72625d7b4fbSAlexey Lapshin }
72725d7b4fbSAlexey Lapshin 
replaceSectionReferences(const DenseMap<SectionBase *,SectionBase * > & FromTo)72825d7b4fbSAlexey Lapshin void SymbolTableSection::replaceSectionReferences(
72925d7b4fbSAlexey Lapshin     const DenseMap<SectionBase *, SectionBase *> &FromTo) {
73025d7b4fbSAlexey Lapshin   for (std::unique_ptr<Symbol> &Sym : Symbols)
73125d7b4fbSAlexey Lapshin     if (SectionBase *To = FromTo.lookup(Sym->DefinedIn))
73225d7b4fbSAlexey Lapshin       Sym->DefinedIn = To;
73325d7b4fbSAlexey Lapshin }
73425d7b4fbSAlexey Lapshin 
initialize(SectionTableRef SecTable)73525d7b4fbSAlexey Lapshin Error SymbolTableSection::initialize(SectionTableRef SecTable) {
73625d7b4fbSAlexey Lapshin   Size = 0;
73725d7b4fbSAlexey Lapshin   Expected<StringTableSection *> Sec =
73825d7b4fbSAlexey Lapshin       SecTable.getSectionOfType<StringTableSection>(
73925d7b4fbSAlexey Lapshin           Link,
74025d7b4fbSAlexey Lapshin           "Symbol table has link index of " + Twine(Link) +
74125d7b4fbSAlexey Lapshin               " which is not a valid index",
74225d7b4fbSAlexey Lapshin           "Symbol table has link index of " + Twine(Link) +
74325d7b4fbSAlexey Lapshin               " which is not a string table");
74425d7b4fbSAlexey Lapshin   if (!Sec)
74525d7b4fbSAlexey Lapshin     return Sec.takeError();
74625d7b4fbSAlexey Lapshin 
74725d7b4fbSAlexey Lapshin   setStrTab(*Sec);
74825d7b4fbSAlexey Lapshin   return Error::success();
74925d7b4fbSAlexey Lapshin }
75025d7b4fbSAlexey Lapshin 
finalize()75125d7b4fbSAlexey Lapshin void SymbolTableSection::finalize() {
75225d7b4fbSAlexey Lapshin   uint32_t MaxLocalIndex = 0;
75325d7b4fbSAlexey Lapshin   for (std::unique_ptr<Symbol> &Sym : Symbols) {
75425d7b4fbSAlexey Lapshin     Sym->NameIndex =
75525d7b4fbSAlexey Lapshin         SymbolNames == nullptr ? 0 : SymbolNames->findIndex(Sym->Name);
75625d7b4fbSAlexey Lapshin     if (Sym->Binding == STB_LOCAL)
75725d7b4fbSAlexey Lapshin       MaxLocalIndex = std::max(MaxLocalIndex, Sym->Index);
75825d7b4fbSAlexey Lapshin   }
75925d7b4fbSAlexey Lapshin   // Now we need to set the Link and Info fields.
76025d7b4fbSAlexey Lapshin   Link = SymbolNames == nullptr ? 0 : SymbolNames->Index;
76125d7b4fbSAlexey Lapshin   Info = MaxLocalIndex + 1;
76225d7b4fbSAlexey Lapshin }
76325d7b4fbSAlexey Lapshin 
prepareForLayout()76425d7b4fbSAlexey Lapshin void SymbolTableSection::prepareForLayout() {
76525d7b4fbSAlexey Lapshin   // Reserve proper amount of space in section index table, so we can
76625d7b4fbSAlexey Lapshin   // layout sections correctly. We will fill the table with correct
76725d7b4fbSAlexey Lapshin   // indexes later in fillShdnxTable.
76825d7b4fbSAlexey Lapshin   if (SectionIndexTable)
76925d7b4fbSAlexey Lapshin     SectionIndexTable->reserve(Symbols.size());
77025d7b4fbSAlexey Lapshin 
77125d7b4fbSAlexey Lapshin   // Add all of our strings to SymbolNames so that SymbolNames has the right
77225d7b4fbSAlexey Lapshin   // size before layout is decided.
77325d7b4fbSAlexey Lapshin   // If the symbol names section has been removed, don't try to add strings to
77425d7b4fbSAlexey Lapshin   // the table.
77525d7b4fbSAlexey Lapshin   if (SymbolNames != nullptr)
77625d7b4fbSAlexey Lapshin     for (std::unique_ptr<Symbol> &Sym : Symbols)
77725d7b4fbSAlexey Lapshin       SymbolNames->addString(Sym->Name);
77825d7b4fbSAlexey Lapshin }
77925d7b4fbSAlexey Lapshin 
fillShndxTable()78025d7b4fbSAlexey Lapshin void SymbolTableSection::fillShndxTable() {
78125d7b4fbSAlexey Lapshin   if (SectionIndexTable == nullptr)
78225d7b4fbSAlexey Lapshin     return;
78325d7b4fbSAlexey Lapshin   // Fill section index table with real section indexes. This function must
78425d7b4fbSAlexey Lapshin   // be called after assignOffsets.
78525d7b4fbSAlexey Lapshin   for (const std::unique_ptr<Symbol> &Sym : Symbols) {
78625d7b4fbSAlexey Lapshin     if (Sym->DefinedIn != nullptr && Sym->DefinedIn->Index >= SHN_LORESERVE)
78725d7b4fbSAlexey Lapshin       SectionIndexTable->addIndex(Sym->DefinedIn->Index);
78825d7b4fbSAlexey Lapshin     else
78925d7b4fbSAlexey Lapshin       SectionIndexTable->addIndex(SHN_UNDEF);
79025d7b4fbSAlexey Lapshin   }
79125d7b4fbSAlexey Lapshin }
79225d7b4fbSAlexey Lapshin 
79325d7b4fbSAlexey Lapshin Expected<const Symbol *>
getSymbolByIndex(uint32_t Index) const79425d7b4fbSAlexey Lapshin SymbolTableSection::getSymbolByIndex(uint32_t Index) const {
79525d7b4fbSAlexey Lapshin   if (Symbols.size() <= Index)
79625d7b4fbSAlexey Lapshin     return createStringError(errc::invalid_argument,
79725d7b4fbSAlexey Lapshin                              "invalid symbol index: " + Twine(Index));
79825d7b4fbSAlexey Lapshin   return Symbols[Index].get();
79925d7b4fbSAlexey Lapshin }
80025d7b4fbSAlexey Lapshin 
getSymbolByIndex(uint32_t Index)80125d7b4fbSAlexey Lapshin Expected<Symbol *> SymbolTableSection::getSymbolByIndex(uint32_t Index) {
80225d7b4fbSAlexey Lapshin   Expected<const Symbol *> Sym =
80325d7b4fbSAlexey Lapshin       static_cast<const SymbolTableSection *>(this)->getSymbolByIndex(Index);
80425d7b4fbSAlexey Lapshin   if (!Sym)
80525d7b4fbSAlexey Lapshin     return Sym.takeError();
80625d7b4fbSAlexey Lapshin 
80725d7b4fbSAlexey Lapshin   return const_cast<Symbol *>(*Sym);
80825d7b4fbSAlexey Lapshin }
80925d7b4fbSAlexey Lapshin 
81025d7b4fbSAlexey Lapshin template <class ELFT>
visit(const SymbolTableSection & Sec)81125d7b4fbSAlexey Lapshin Error ELFSectionWriter<ELFT>::visit(const SymbolTableSection &Sec) {
81225d7b4fbSAlexey Lapshin   Elf_Sym *Sym = reinterpret_cast<Elf_Sym *>(Out.getBufferStart() + Sec.Offset);
81325d7b4fbSAlexey Lapshin   // Loop though symbols setting each entry of the symbol table.
81425d7b4fbSAlexey Lapshin   for (const std::unique_ptr<Symbol> &Symbol : Sec.Symbols) {
81525d7b4fbSAlexey Lapshin     Sym->st_name = Symbol->NameIndex;
81625d7b4fbSAlexey Lapshin     Sym->st_value = Symbol->Value;
81725d7b4fbSAlexey Lapshin     Sym->st_size = Symbol->Size;
81825d7b4fbSAlexey Lapshin     Sym->st_other = Symbol->Visibility;
81925d7b4fbSAlexey Lapshin     Sym->setBinding(Symbol->Binding);
82025d7b4fbSAlexey Lapshin     Sym->setType(Symbol->Type);
82125d7b4fbSAlexey Lapshin     Sym->st_shndx = Symbol->getShndx();
82225d7b4fbSAlexey Lapshin     ++Sym;
82325d7b4fbSAlexey Lapshin   }
82425d7b4fbSAlexey Lapshin   return Error::success();
82525d7b4fbSAlexey Lapshin }
82625d7b4fbSAlexey Lapshin 
accept(SectionVisitor & Visitor) const82725d7b4fbSAlexey Lapshin Error SymbolTableSection::accept(SectionVisitor &Visitor) const {
82825d7b4fbSAlexey Lapshin   return Visitor.visit(*this);
82925d7b4fbSAlexey Lapshin }
83025d7b4fbSAlexey Lapshin 
accept(MutableSectionVisitor & Visitor)83125d7b4fbSAlexey Lapshin Error SymbolTableSection::accept(MutableSectionVisitor &Visitor) {
83225d7b4fbSAlexey Lapshin   return Visitor.visit(*this);
83325d7b4fbSAlexey Lapshin }
83425d7b4fbSAlexey Lapshin 
getNamePrefix() const83525d7b4fbSAlexey Lapshin StringRef RelocationSectionBase::getNamePrefix() const {
83625d7b4fbSAlexey Lapshin   switch (Type) {
83725d7b4fbSAlexey Lapshin   case SHT_REL:
83825d7b4fbSAlexey Lapshin     return ".rel";
83925d7b4fbSAlexey Lapshin   case SHT_RELA:
84025d7b4fbSAlexey Lapshin     return ".rela";
84125d7b4fbSAlexey Lapshin   default:
84225d7b4fbSAlexey Lapshin     llvm_unreachable("not a relocation section");
84325d7b4fbSAlexey Lapshin   }
84425d7b4fbSAlexey Lapshin }
84525d7b4fbSAlexey Lapshin 
removeSectionReferences(bool AllowBrokenLinks,function_ref<bool (const SectionBase *)> ToRemove)84625d7b4fbSAlexey Lapshin Error RelocationSection::removeSectionReferences(
84725d7b4fbSAlexey Lapshin     bool AllowBrokenLinks, function_ref<bool(const SectionBase *)> ToRemove) {
84825d7b4fbSAlexey Lapshin   if (ToRemove(Symbols)) {
84925d7b4fbSAlexey Lapshin     if (!AllowBrokenLinks)
85025d7b4fbSAlexey Lapshin       return createStringError(
85125d7b4fbSAlexey Lapshin           llvm::errc::invalid_argument,
85225d7b4fbSAlexey Lapshin           "symbol table '%s' cannot be removed because it is "
85325d7b4fbSAlexey Lapshin           "referenced by the relocation section '%s'",
85425d7b4fbSAlexey Lapshin           Symbols->Name.data(), this->Name.data());
85525d7b4fbSAlexey Lapshin     Symbols = nullptr;
85625d7b4fbSAlexey Lapshin   }
85725d7b4fbSAlexey Lapshin 
85825d7b4fbSAlexey Lapshin   for (const Relocation &R : Relocations) {
85925d7b4fbSAlexey Lapshin     if (!R.RelocSymbol || !R.RelocSymbol->DefinedIn ||
86025d7b4fbSAlexey Lapshin         !ToRemove(R.RelocSymbol->DefinedIn))
86125d7b4fbSAlexey Lapshin       continue;
86225d7b4fbSAlexey Lapshin     return createStringError(llvm::errc::invalid_argument,
86325d7b4fbSAlexey Lapshin                              "section '%s' cannot be removed: (%s+0x%" PRIx64
86425d7b4fbSAlexey Lapshin                              ") has relocation against symbol '%s'",
86525d7b4fbSAlexey Lapshin                              R.RelocSymbol->DefinedIn->Name.data(),
86625d7b4fbSAlexey Lapshin                              SecToApplyRel->Name.data(), R.Offset,
86725d7b4fbSAlexey Lapshin                              R.RelocSymbol->Name.c_str());
86825d7b4fbSAlexey Lapshin   }
86925d7b4fbSAlexey Lapshin 
87025d7b4fbSAlexey Lapshin   return Error::success();
87125d7b4fbSAlexey Lapshin }
87225d7b4fbSAlexey Lapshin 
87325d7b4fbSAlexey Lapshin template <class SymTabType>
initialize(SectionTableRef SecTable)87425d7b4fbSAlexey Lapshin Error RelocSectionWithSymtabBase<SymTabType>::initialize(
87525d7b4fbSAlexey Lapshin     SectionTableRef SecTable) {
87625d7b4fbSAlexey Lapshin   if (Link != SHN_UNDEF) {
87725d7b4fbSAlexey Lapshin     Expected<SymTabType *> Sec = SecTable.getSectionOfType<SymTabType>(
87825d7b4fbSAlexey Lapshin         Link,
87925d7b4fbSAlexey Lapshin         "Link field value " + Twine(Link) + " in section " + Name +
88025d7b4fbSAlexey Lapshin             " is invalid",
88125d7b4fbSAlexey Lapshin         "Link field value " + Twine(Link) + " in section " + Name +
88225d7b4fbSAlexey Lapshin             " is not a symbol table");
88325d7b4fbSAlexey Lapshin     if (!Sec)
88425d7b4fbSAlexey Lapshin       return Sec.takeError();
88525d7b4fbSAlexey Lapshin 
88625d7b4fbSAlexey Lapshin     setSymTab(*Sec);
88725d7b4fbSAlexey Lapshin   }
88825d7b4fbSAlexey Lapshin 
88925d7b4fbSAlexey Lapshin   if (Info != SHN_UNDEF) {
89025d7b4fbSAlexey Lapshin     Expected<SectionBase *> Sec =
89125d7b4fbSAlexey Lapshin         SecTable.getSection(Info, "Info field value " + Twine(Info) +
89225d7b4fbSAlexey Lapshin                                       " in section " + Name + " is invalid");
89325d7b4fbSAlexey Lapshin     if (!Sec)
89425d7b4fbSAlexey Lapshin       return Sec.takeError();
89525d7b4fbSAlexey Lapshin 
89625d7b4fbSAlexey Lapshin     setSection(*Sec);
89725d7b4fbSAlexey Lapshin   } else
89825d7b4fbSAlexey Lapshin     setSection(nullptr);
89925d7b4fbSAlexey Lapshin 
90025d7b4fbSAlexey Lapshin   return Error::success();
90125d7b4fbSAlexey Lapshin }
90225d7b4fbSAlexey Lapshin 
90325d7b4fbSAlexey Lapshin template <class SymTabType>
finalize()90425d7b4fbSAlexey Lapshin void RelocSectionWithSymtabBase<SymTabType>::finalize() {
90525d7b4fbSAlexey Lapshin   this->Link = Symbols ? Symbols->Index : 0;
90625d7b4fbSAlexey Lapshin 
90725d7b4fbSAlexey Lapshin   if (SecToApplyRel != nullptr)
90825d7b4fbSAlexey Lapshin     this->Info = SecToApplyRel->Index;
90925d7b4fbSAlexey Lapshin }
91025d7b4fbSAlexey Lapshin 
91125d7b4fbSAlexey Lapshin template <class ELFT>
setAddend(Elf_Rel_Impl<ELFT,false> &,uint64_t)91225d7b4fbSAlexey Lapshin static void setAddend(Elf_Rel_Impl<ELFT, false> &, uint64_t) {}
91325d7b4fbSAlexey Lapshin 
91425d7b4fbSAlexey Lapshin template <class ELFT>
setAddend(Elf_Rel_Impl<ELFT,true> & Rela,uint64_t Addend)91525d7b4fbSAlexey Lapshin static void setAddend(Elf_Rel_Impl<ELFT, true> &Rela, uint64_t Addend) {
91625d7b4fbSAlexey Lapshin   Rela.r_addend = Addend;
91725d7b4fbSAlexey Lapshin }
91825d7b4fbSAlexey Lapshin 
91925d7b4fbSAlexey Lapshin template <class RelRange, class T>
writeRel(const RelRange & Relocations,T * Buf,bool IsMips64EL)92025d7b4fbSAlexey Lapshin static void writeRel(const RelRange &Relocations, T *Buf, bool IsMips64EL) {
92125d7b4fbSAlexey Lapshin   for (const auto &Reloc : Relocations) {
92225d7b4fbSAlexey Lapshin     Buf->r_offset = Reloc.Offset;
92325d7b4fbSAlexey Lapshin     setAddend(*Buf, Reloc.Addend);
92425d7b4fbSAlexey Lapshin     Buf->setSymbolAndType(Reloc.RelocSymbol ? Reloc.RelocSymbol->Index : 0,
92525d7b4fbSAlexey Lapshin                           Reloc.Type, IsMips64EL);
92625d7b4fbSAlexey Lapshin     ++Buf;
92725d7b4fbSAlexey Lapshin   }
92825d7b4fbSAlexey Lapshin }
92925d7b4fbSAlexey Lapshin 
93025d7b4fbSAlexey Lapshin template <class ELFT>
visit(const RelocationSection & Sec)93125d7b4fbSAlexey Lapshin Error ELFSectionWriter<ELFT>::visit(const RelocationSection &Sec) {
93225d7b4fbSAlexey Lapshin   uint8_t *Buf = reinterpret_cast<uint8_t *>(Out.getBufferStart()) + Sec.Offset;
93325d7b4fbSAlexey Lapshin   if (Sec.Type == SHT_REL)
93425d7b4fbSAlexey Lapshin     writeRel(Sec.Relocations, reinterpret_cast<Elf_Rel *>(Buf),
93525d7b4fbSAlexey Lapshin              Sec.getObject().IsMips64EL);
93625d7b4fbSAlexey Lapshin   else
93725d7b4fbSAlexey Lapshin     writeRel(Sec.Relocations, reinterpret_cast<Elf_Rela *>(Buf),
93825d7b4fbSAlexey Lapshin              Sec.getObject().IsMips64EL);
93925d7b4fbSAlexey Lapshin   return Error::success();
94025d7b4fbSAlexey Lapshin }
94125d7b4fbSAlexey Lapshin 
accept(SectionVisitor & Visitor) const94225d7b4fbSAlexey Lapshin Error RelocationSection::accept(SectionVisitor &Visitor) const {
94325d7b4fbSAlexey Lapshin   return Visitor.visit(*this);
94425d7b4fbSAlexey Lapshin }
94525d7b4fbSAlexey Lapshin 
accept(MutableSectionVisitor & Visitor)94625d7b4fbSAlexey Lapshin Error RelocationSection::accept(MutableSectionVisitor &Visitor) {
94725d7b4fbSAlexey Lapshin   return Visitor.visit(*this);
94825d7b4fbSAlexey Lapshin }
94925d7b4fbSAlexey Lapshin 
removeSymbols(function_ref<bool (const Symbol &)> ToRemove)95025d7b4fbSAlexey Lapshin Error RelocationSection::removeSymbols(
95125d7b4fbSAlexey Lapshin     function_ref<bool(const Symbol &)> ToRemove) {
95225d7b4fbSAlexey Lapshin   for (const Relocation &Reloc : Relocations)
95325d7b4fbSAlexey Lapshin     if (Reloc.RelocSymbol && ToRemove(*Reloc.RelocSymbol))
95425d7b4fbSAlexey Lapshin       return createStringError(
95525d7b4fbSAlexey Lapshin           llvm::errc::invalid_argument,
95625d7b4fbSAlexey Lapshin           "not stripping symbol '%s' because it is named in a relocation",
95725d7b4fbSAlexey Lapshin           Reloc.RelocSymbol->Name.data());
95825d7b4fbSAlexey Lapshin   return Error::success();
95925d7b4fbSAlexey Lapshin }
96025d7b4fbSAlexey Lapshin 
markSymbols()96125d7b4fbSAlexey Lapshin void RelocationSection::markSymbols() {
96225d7b4fbSAlexey Lapshin   for (const Relocation &Reloc : Relocations)
96325d7b4fbSAlexey Lapshin     if (Reloc.RelocSymbol)
96425d7b4fbSAlexey Lapshin       Reloc.RelocSymbol->Referenced = true;
96525d7b4fbSAlexey Lapshin }
96625d7b4fbSAlexey Lapshin 
replaceSectionReferences(const DenseMap<SectionBase *,SectionBase * > & FromTo)96725d7b4fbSAlexey Lapshin void RelocationSection::replaceSectionReferences(
96825d7b4fbSAlexey Lapshin     const DenseMap<SectionBase *, SectionBase *> &FromTo) {
96925d7b4fbSAlexey Lapshin   // Update the target section if it was replaced.
97025d7b4fbSAlexey Lapshin   if (SectionBase *To = FromTo.lookup(SecToApplyRel))
97125d7b4fbSAlexey Lapshin     SecToApplyRel = To;
97225d7b4fbSAlexey Lapshin }
97325d7b4fbSAlexey Lapshin 
visit(const DynamicRelocationSection & Sec)97425d7b4fbSAlexey Lapshin Error SectionWriter::visit(const DynamicRelocationSection &Sec) {
97525d7b4fbSAlexey Lapshin   llvm::copy(Sec.Contents, Out.getBufferStart() + Sec.Offset);
97625d7b4fbSAlexey Lapshin   return Error::success();
97725d7b4fbSAlexey Lapshin }
97825d7b4fbSAlexey Lapshin 
accept(SectionVisitor & Visitor) const97925d7b4fbSAlexey Lapshin Error DynamicRelocationSection::accept(SectionVisitor &Visitor) const {
98025d7b4fbSAlexey Lapshin   return Visitor.visit(*this);
98125d7b4fbSAlexey Lapshin }
98225d7b4fbSAlexey Lapshin 
accept(MutableSectionVisitor & Visitor)98325d7b4fbSAlexey Lapshin Error DynamicRelocationSection::accept(MutableSectionVisitor &Visitor) {
98425d7b4fbSAlexey Lapshin   return Visitor.visit(*this);
98525d7b4fbSAlexey Lapshin }
98625d7b4fbSAlexey Lapshin 
removeSectionReferences(bool AllowBrokenLinks,function_ref<bool (const SectionBase *)> ToRemove)98725d7b4fbSAlexey Lapshin Error DynamicRelocationSection::removeSectionReferences(
98825d7b4fbSAlexey Lapshin     bool AllowBrokenLinks, function_ref<bool(const SectionBase *)> ToRemove) {
98925d7b4fbSAlexey Lapshin   if (ToRemove(Symbols)) {
99025d7b4fbSAlexey Lapshin     if (!AllowBrokenLinks)
99125d7b4fbSAlexey Lapshin       return createStringError(
99225d7b4fbSAlexey Lapshin           llvm::errc::invalid_argument,
99325d7b4fbSAlexey Lapshin           "symbol table '%s' cannot be removed because it is "
99425d7b4fbSAlexey Lapshin           "referenced by the relocation section '%s'",
99525d7b4fbSAlexey Lapshin           Symbols->Name.data(), this->Name.data());
99625d7b4fbSAlexey Lapshin     Symbols = nullptr;
99725d7b4fbSAlexey Lapshin   }
99825d7b4fbSAlexey Lapshin 
99925d7b4fbSAlexey Lapshin   // SecToApplyRel contains a section referenced by sh_info field. It keeps
100025d7b4fbSAlexey Lapshin   // a section to which the relocation section applies. When we remove any
100125d7b4fbSAlexey Lapshin   // sections we also remove their relocation sections. Since we do that much
100225d7b4fbSAlexey Lapshin   // earlier, this assert should never be triggered.
100325d7b4fbSAlexey Lapshin   assert(!SecToApplyRel || !ToRemove(SecToApplyRel));
100425d7b4fbSAlexey Lapshin   return Error::success();
100525d7b4fbSAlexey Lapshin }
100625d7b4fbSAlexey Lapshin 
removeSectionReferences(bool AllowBrokenDependency,function_ref<bool (const SectionBase *)> ToRemove)100725d7b4fbSAlexey Lapshin Error Section::removeSectionReferences(
100825d7b4fbSAlexey Lapshin     bool AllowBrokenDependency,
100925d7b4fbSAlexey Lapshin     function_ref<bool(const SectionBase *)> ToRemove) {
101025d7b4fbSAlexey Lapshin   if (ToRemove(LinkSection)) {
101125d7b4fbSAlexey Lapshin     if (!AllowBrokenDependency)
101225d7b4fbSAlexey Lapshin       return createStringError(llvm::errc::invalid_argument,
101325d7b4fbSAlexey Lapshin                                "section '%s' cannot be removed because it is "
101425d7b4fbSAlexey Lapshin                                "referenced by the section '%s'",
101525d7b4fbSAlexey Lapshin                                LinkSection->Name.data(), this->Name.data());
101625d7b4fbSAlexey Lapshin     LinkSection = nullptr;
101725d7b4fbSAlexey Lapshin   }
101825d7b4fbSAlexey Lapshin   return Error::success();
101925d7b4fbSAlexey Lapshin }
102025d7b4fbSAlexey Lapshin 
finalize()102125d7b4fbSAlexey Lapshin void GroupSection::finalize() {
102225d7b4fbSAlexey Lapshin   this->Info = Sym ? Sym->Index : 0;
102325d7b4fbSAlexey Lapshin   this->Link = SymTab ? SymTab->Index : 0;
102425d7b4fbSAlexey Lapshin   // Linker deduplication for GRP_COMDAT is based on Sym->Name. The local/global
102525d7b4fbSAlexey Lapshin   // status is not part of the equation. If Sym is localized, the intention is
102625d7b4fbSAlexey Lapshin   // likely to make the group fully localized. Drop GRP_COMDAT to suppress
102725d7b4fbSAlexey Lapshin   // deduplication. See https://groups.google.com/g/generic-abi/c/2X6mR-s2zoc
102825d7b4fbSAlexey Lapshin   if ((FlagWord & GRP_COMDAT) && Sym && Sym->Binding == STB_LOCAL)
102925d7b4fbSAlexey Lapshin     this->FlagWord &= ~GRP_COMDAT;
103025d7b4fbSAlexey Lapshin }
103125d7b4fbSAlexey Lapshin 
removeSectionReferences(bool AllowBrokenLinks,function_ref<bool (const SectionBase *)> ToRemove)103225d7b4fbSAlexey Lapshin Error GroupSection::removeSectionReferences(
103325d7b4fbSAlexey Lapshin     bool AllowBrokenLinks, function_ref<bool(const SectionBase *)> ToRemove) {
103425d7b4fbSAlexey Lapshin   if (ToRemove(SymTab)) {
103525d7b4fbSAlexey Lapshin     if (!AllowBrokenLinks)
103625d7b4fbSAlexey Lapshin       return createStringError(
103725d7b4fbSAlexey Lapshin           llvm::errc::invalid_argument,
103825d7b4fbSAlexey Lapshin           "section '.symtab' cannot be removed because it is "
103925d7b4fbSAlexey Lapshin           "referenced by the group section '%s'",
104025d7b4fbSAlexey Lapshin           this->Name.data());
104125d7b4fbSAlexey Lapshin     SymTab = nullptr;
104225d7b4fbSAlexey Lapshin     Sym = nullptr;
104325d7b4fbSAlexey Lapshin   }
104425d7b4fbSAlexey Lapshin   llvm::erase_if(GroupMembers, ToRemove);
104525d7b4fbSAlexey Lapshin   return Error::success();
104625d7b4fbSAlexey Lapshin }
104725d7b4fbSAlexey Lapshin 
removeSymbols(function_ref<bool (const Symbol &)> ToRemove)104825d7b4fbSAlexey Lapshin Error GroupSection::removeSymbols(function_ref<bool(const Symbol &)> ToRemove) {
104925d7b4fbSAlexey Lapshin   if (ToRemove(*Sym))
105025d7b4fbSAlexey Lapshin     return createStringError(llvm::errc::invalid_argument,
105125d7b4fbSAlexey Lapshin                              "symbol '%s' cannot be removed because it is "
105225d7b4fbSAlexey Lapshin                              "referenced by the section '%s[%d]'",
105325d7b4fbSAlexey Lapshin                              Sym->Name.data(), this->Name.data(), this->Index);
105425d7b4fbSAlexey Lapshin   return Error::success();
105525d7b4fbSAlexey Lapshin }
105625d7b4fbSAlexey Lapshin 
markSymbols()105725d7b4fbSAlexey Lapshin void GroupSection::markSymbols() {
105825d7b4fbSAlexey Lapshin   if (Sym)
105925d7b4fbSAlexey Lapshin     Sym->Referenced = true;
106025d7b4fbSAlexey Lapshin }
106125d7b4fbSAlexey Lapshin 
replaceSectionReferences(const DenseMap<SectionBase *,SectionBase * > & FromTo)106225d7b4fbSAlexey Lapshin void GroupSection::replaceSectionReferences(
106325d7b4fbSAlexey Lapshin     const DenseMap<SectionBase *, SectionBase *> &FromTo) {
106425d7b4fbSAlexey Lapshin   for (SectionBase *&Sec : GroupMembers)
106525d7b4fbSAlexey Lapshin     if (SectionBase *To = FromTo.lookup(Sec))
106625d7b4fbSAlexey Lapshin       Sec = To;
106725d7b4fbSAlexey Lapshin }
106825d7b4fbSAlexey Lapshin 
onRemove()106925d7b4fbSAlexey Lapshin void GroupSection::onRemove() {
107025d7b4fbSAlexey Lapshin   // As the header section of the group is removed, drop the Group flag in its
107125d7b4fbSAlexey Lapshin   // former members.
107225d7b4fbSAlexey Lapshin   for (SectionBase *Sec : GroupMembers)
107325d7b4fbSAlexey Lapshin     Sec->Flags &= ~SHF_GROUP;
107425d7b4fbSAlexey Lapshin }
107525d7b4fbSAlexey Lapshin 
initialize(SectionTableRef SecTable)107625d7b4fbSAlexey Lapshin Error Section::initialize(SectionTableRef SecTable) {
107725d7b4fbSAlexey Lapshin   if (Link == ELF::SHN_UNDEF)
107825d7b4fbSAlexey Lapshin     return Error::success();
107925d7b4fbSAlexey Lapshin 
108025d7b4fbSAlexey Lapshin   Expected<SectionBase *> Sec =
108125d7b4fbSAlexey Lapshin       SecTable.getSection(Link, "Link field value " + Twine(Link) +
108225d7b4fbSAlexey Lapshin                                     " in section " + Name + " is invalid");
108325d7b4fbSAlexey Lapshin   if (!Sec)
108425d7b4fbSAlexey Lapshin     return Sec.takeError();
108525d7b4fbSAlexey Lapshin 
108625d7b4fbSAlexey Lapshin   LinkSection = *Sec;
108725d7b4fbSAlexey Lapshin 
108825d7b4fbSAlexey Lapshin   if (LinkSection->Type == ELF::SHT_SYMTAB)
108925d7b4fbSAlexey Lapshin     LinkSection = nullptr;
109025d7b4fbSAlexey Lapshin 
109125d7b4fbSAlexey Lapshin   return Error::success();
109225d7b4fbSAlexey Lapshin }
109325d7b4fbSAlexey Lapshin 
finalize()109425d7b4fbSAlexey Lapshin void Section::finalize() { this->Link = LinkSection ? LinkSection->Index : 0; }
109525d7b4fbSAlexey Lapshin 
init(StringRef File)109625d7b4fbSAlexey Lapshin void GnuDebugLinkSection::init(StringRef File) {
109725d7b4fbSAlexey Lapshin   FileName = sys::path::filename(File);
109825d7b4fbSAlexey Lapshin   // The format for the .gnu_debuglink starts with the file name and is
109925d7b4fbSAlexey Lapshin   // followed by a null terminator and then the CRC32 of the file. The CRC32
110025d7b4fbSAlexey Lapshin   // should be 4 byte aligned. So we add the FileName size, a 1 for the null
110125d7b4fbSAlexey Lapshin   // byte, and then finally push the size to alignment and add 4.
110225d7b4fbSAlexey Lapshin   Size = alignTo(FileName.size() + 1, 4) + 4;
110325d7b4fbSAlexey Lapshin   // The CRC32 will only be aligned if we align the whole section.
110425d7b4fbSAlexey Lapshin   Align = 4;
110525d7b4fbSAlexey Lapshin   Type = OriginalType = ELF::SHT_PROGBITS;
110625d7b4fbSAlexey Lapshin   Name = ".gnu_debuglink";
110725d7b4fbSAlexey Lapshin   // For sections not found in segments, OriginalOffset is only used to
110825d7b4fbSAlexey Lapshin   // establish the order that sections should go in. By using the maximum
110925d7b4fbSAlexey Lapshin   // possible offset we cause this section to wind up at the end.
111025d7b4fbSAlexey Lapshin   OriginalOffset = std::numeric_limits<uint64_t>::max();
111125d7b4fbSAlexey Lapshin }
111225d7b4fbSAlexey Lapshin 
GnuDebugLinkSection(StringRef File,uint32_t PrecomputedCRC)111325d7b4fbSAlexey Lapshin GnuDebugLinkSection::GnuDebugLinkSection(StringRef File,
111425d7b4fbSAlexey Lapshin                                          uint32_t PrecomputedCRC)
111525d7b4fbSAlexey Lapshin     : FileName(File), CRC32(PrecomputedCRC) {
111625d7b4fbSAlexey Lapshin   init(File);
111725d7b4fbSAlexey Lapshin }
111825d7b4fbSAlexey Lapshin 
111925d7b4fbSAlexey Lapshin template <class ELFT>
visit(const GnuDebugLinkSection & Sec)112025d7b4fbSAlexey Lapshin Error ELFSectionWriter<ELFT>::visit(const GnuDebugLinkSection &Sec) {
112125d7b4fbSAlexey Lapshin   unsigned char *Buf =
112225d7b4fbSAlexey Lapshin       reinterpret_cast<uint8_t *>(Out.getBufferStart()) + Sec.Offset;
112325d7b4fbSAlexey Lapshin   Elf_Word *CRC =
112425d7b4fbSAlexey Lapshin       reinterpret_cast<Elf_Word *>(Buf + Sec.Size - sizeof(Elf_Word));
112525d7b4fbSAlexey Lapshin   *CRC = Sec.CRC32;
112625d7b4fbSAlexey Lapshin   llvm::copy(Sec.FileName, Buf);
112725d7b4fbSAlexey Lapshin   return Error::success();
112825d7b4fbSAlexey Lapshin }
112925d7b4fbSAlexey Lapshin 
accept(SectionVisitor & Visitor) const113025d7b4fbSAlexey Lapshin Error GnuDebugLinkSection::accept(SectionVisitor &Visitor) const {
113125d7b4fbSAlexey Lapshin   return Visitor.visit(*this);
113225d7b4fbSAlexey Lapshin }
113325d7b4fbSAlexey Lapshin 
accept(MutableSectionVisitor & Visitor)113425d7b4fbSAlexey Lapshin Error GnuDebugLinkSection::accept(MutableSectionVisitor &Visitor) {
113525d7b4fbSAlexey Lapshin   return Visitor.visit(*this);
113625d7b4fbSAlexey Lapshin }
113725d7b4fbSAlexey Lapshin 
113825d7b4fbSAlexey Lapshin template <class ELFT>
visit(const GroupSection & Sec)113925d7b4fbSAlexey Lapshin Error ELFSectionWriter<ELFT>::visit(const GroupSection &Sec) {
114025d7b4fbSAlexey Lapshin   ELF::Elf32_Word *Buf =
114125d7b4fbSAlexey Lapshin       reinterpret_cast<ELF::Elf32_Word *>(Out.getBufferStart() + Sec.Offset);
114225d7b4fbSAlexey Lapshin   support::endian::write32<ELFT::TargetEndianness>(Buf++, Sec.FlagWord);
114325d7b4fbSAlexey Lapshin   for (SectionBase *S : Sec.GroupMembers)
114425d7b4fbSAlexey Lapshin     support::endian::write32<ELFT::TargetEndianness>(Buf++, S->Index);
114525d7b4fbSAlexey Lapshin   return Error::success();
114625d7b4fbSAlexey Lapshin }
114725d7b4fbSAlexey Lapshin 
accept(SectionVisitor & Visitor) const114825d7b4fbSAlexey Lapshin Error GroupSection::accept(SectionVisitor &Visitor) const {
114925d7b4fbSAlexey Lapshin   return Visitor.visit(*this);
115025d7b4fbSAlexey Lapshin }
115125d7b4fbSAlexey Lapshin 
accept(MutableSectionVisitor & Visitor)115225d7b4fbSAlexey Lapshin Error GroupSection::accept(MutableSectionVisitor &Visitor) {
115325d7b4fbSAlexey Lapshin   return Visitor.visit(*this);
115425d7b4fbSAlexey Lapshin }
115525d7b4fbSAlexey Lapshin 
115625d7b4fbSAlexey Lapshin // Returns true IFF a section is wholly inside the range of a segment
sectionWithinSegment(const SectionBase & Sec,const Segment & Seg)115725d7b4fbSAlexey Lapshin static bool sectionWithinSegment(const SectionBase &Sec, const Segment &Seg) {
115825d7b4fbSAlexey Lapshin   // If a section is empty it should be treated like it has a size of 1. This is
115925d7b4fbSAlexey Lapshin   // to clarify the case when an empty section lies on a boundary between two
116025d7b4fbSAlexey Lapshin   // segments and ensures that the section "belongs" to the second segment and
116125d7b4fbSAlexey Lapshin   // not the first.
116225d7b4fbSAlexey Lapshin   uint64_t SecSize = Sec.Size ? Sec.Size : 1;
116325d7b4fbSAlexey Lapshin 
116425d7b4fbSAlexey Lapshin   // Ignore just added sections.
116525d7b4fbSAlexey Lapshin   if (Sec.OriginalOffset == std::numeric_limits<uint64_t>::max())
116625d7b4fbSAlexey Lapshin     return false;
116725d7b4fbSAlexey Lapshin 
116825d7b4fbSAlexey Lapshin   if (Sec.Type == SHT_NOBITS) {
116925d7b4fbSAlexey Lapshin     if (!(Sec.Flags & SHF_ALLOC))
117025d7b4fbSAlexey Lapshin       return false;
117125d7b4fbSAlexey Lapshin 
117225d7b4fbSAlexey Lapshin     bool SectionIsTLS = Sec.Flags & SHF_TLS;
117325d7b4fbSAlexey Lapshin     bool SegmentIsTLS = Seg.Type == PT_TLS;
117425d7b4fbSAlexey Lapshin     if (SectionIsTLS != SegmentIsTLS)
117525d7b4fbSAlexey Lapshin       return false;
117625d7b4fbSAlexey Lapshin 
117725d7b4fbSAlexey Lapshin     return Seg.VAddr <= Sec.Addr &&
117825d7b4fbSAlexey Lapshin            Seg.VAddr + Seg.MemSize >= Sec.Addr + SecSize;
117925d7b4fbSAlexey Lapshin   }
118025d7b4fbSAlexey Lapshin 
118125d7b4fbSAlexey Lapshin   return Seg.Offset <= Sec.OriginalOffset &&
118225d7b4fbSAlexey Lapshin          Seg.Offset + Seg.FileSize >= Sec.OriginalOffset + SecSize;
118325d7b4fbSAlexey Lapshin }
118425d7b4fbSAlexey Lapshin 
118525d7b4fbSAlexey Lapshin // Returns true IFF a segment's original offset is inside of another segment's
118625d7b4fbSAlexey Lapshin // range.
segmentOverlapsSegment(const Segment & Child,const Segment & Parent)118725d7b4fbSAlexey Lapshin static bool segmentOverlapsSegment(const Segment &Child,
118825d7b4fbSAlexey Lapshin                                    const Segment &Parent) {
118925d7b4fbSAlexey Lapshin 
119025d7b4fbSAlexey Lapshin   return Parent.OriginalOffset <= Child.OriginalOffset &&
119125d7b4fbSAlexey Lapshin          Parent.OriginalOffset + Parent.FileSize > Child.OriginalOffset;
119225d7b4fbSAlexey Lapshin }
119325d7b4fbSAlexey Lapshin 
compareSegmentsByOffset(const Segment * A,const Segment * B)119425d7b4fbSAlexey Lapshin static bool compareSegmentsByOffset(const Segment *A, const Segment *B) {
119525d7b4fbSAlexey Lapshin   // Any segment without a parent segment should come before a segment
119625d7b4fbSAlexey Lapshin   // that has a parent segment.
119725d7b4fbSAlexey Lapshin   if (A->OriginalOffset < B->OriginalOffset)
119825d7b4fbSAlexey Lapshin     return true;
119925d7b4fbSAlexey Lapshin   if (A->OriginalOffset > B->OriginalOffset)
120025d7b4fbSAlexey Lapshin     return false;
120125d7b4fbSAlexey Lapshin   return A->Index < B->Index;
120225d7b4fbSAlexey Lapshin }
120325d7b4fbSAlexey Lapshin 
initFileHeader()120425d7b4fbSAlexey Lapshin void BasicELFBuilder::initFileHeader() {
120525d7b4fbSAlexey Lapshin   Obj->Flags = 0x0;
120625d7b4fbSAlexey Lapshin   Obj->Type = ET_REL;
120725d7b4fbSAlexey Lapshin   Obj->OSABI = ELFOSABI_NONE;
120825d7b4fbSAlexey Lapshin   Obj->ABIVersion = 0;
120925d7b4fbSAlexey Lapshin   Obj->Entry = 0x0;
121025d7b4fbSAlexey Lapshin   Obj->Machine = EM_NONE;
121125d7b4fbSAlexey Lapshin   Obj->Version = 1;
121225d7b4fbSAlexey Lapshin }
121325d7b4fbSAlexey Lapshin 
initHeaderSegment()121425d7b4fbSAlexey Lapshin void BasicELFBuilder::initHeaderSegment() { Obj->ElfHdrSegment.Index = 0; }
121525d7b4fbSAlexey Lapshin 
addStrTab()121625d7b4fbSAlexey Lapshin StringTableSection *BasicELFBuilder::addStrTab() {
121725d7b4fbSAlexey Lapshin   auto &StrTab = Obj->addSection<StringTableSection>();
121825d7b4fbSAlexey Lapshin   StrTab.Name = ".strtab";
121925d7b4fbSAlexey Lapshin 
122025d7b4fbSAlexey Lapshin   Obj->SectionNames = &StrTab;
122125d7b4fbSAlexey Lapshin   return &StrTab;
122225d7b4fbSAlexey Lapshin }
122325d7b4fbSAlexey Lapshin 
addSymTab(StringTableSection * StrTab)122425d7b4fbSAlexey Lapshin SymbolTableSection *BasicELFBuilder::addSymTab(StringTableSection *StrTab) {
122525d7b4fbSAlexey Lapshin   auto &SymTab = Obj->addSection<SymbolTableSection>();
122625d7b4fbSAlexey Lapshin 
122725d7b4fbSAlexey Lapshin   SymTab.Name = ".symtab";
122825d7b4fbSAlexey Lapshin   SymTab.Link = StrTab->Index;
122925d7b4fbSAlexey Lapshin 
123025d7b4fbSAlexey Lapshin   // The symbol table always needs a null symbol
123125d7b4fbSAlexey Lapshin   SymTab.addSymbol("", 0, 0, nullptr, 0, 0, 0, 0);
123225d7b4fbSAlexey Lapshin 
123325d7b4fbSAlexey Lapshin   Obj->SymbolTable = &SymTab;
123425d7b4fbSAlexey Lapshin   return &SymTab;
123525d7b4fbSAlexey Lapshin }
123625d7b4fbSAlexey Lapshin 
initSections()123725d7b4fbSAlexey Lapshin Error BasicELFBuilder::initSections() {
123825d7b4fbSAlexey Lapshin   for (SectionBase &Sec : Obj->sections())
123925d7b4fbSAlexey Lapshin     if (Error Err = Sec.initialize(Obj->sections()))
124025d7b4fbSAlexey Lapshin       return Err;
124125d7b4fbSAlexey Lapshin 
124225d7b4fbSAlexey Lapshin   return Error::success();
124325d7b4fbSAlexey Lapshin }
124425d7b4fbSAlexey Lapshin 
addData(SymbolTableSection * SymTab)124525d7b4fbSAlexey Lapshin void BinaryELFBuilder::addData(SymbolTableSection *SymTab) {
124625d7b4fbSAlexey Lapshin   auto Data = ArrayRef<uint8_t>(
124725d7b4fbSAlexey Lapshin       reinterpret_cast<const uint8_t *>(MemBuf->getBufferStart()),
124825d7b4fbSAlexey Lapshin       MemBuf->getBufferSize());
124925d7b4fbSAlexey Lapshin   auto &DataSection = Obj->addSection<Section>(Data);
125025d7b4fbSAlexey Lapshin   DataSection.Name = ".data";
125125d7b4fbSAlexey Lapshin   DataSection.Type = ELF::SHT_PROGBITS;
125225d7b4fbSAlexey Lapshin   DataSection.Size = Data.size();
125325d7b4fbSAlexey Lapshin   DataSection.Flags = ELF::SHF_ALLOC | ELF::SHF_WRITE;
125425d7b4fbSAlexey Lapshin 
125525d7b4fbSAlexey Lapshin   std::string SanitizedFilename = MemBuf->getBufferIdentifier().str();
125625d7b4fbSAlexey Lapshin   std::replace_if(
125725d7b4fbSAlexey Lapshin       std::begin(SanitizedFilename), std::end(SanitizedFilename),
125825d7b4fbSAlexey Lapshin       [](char C) { return !isAlnum(C); }, '_');
125925d7b4fbSAlexey Lapshin   Twine Prefix = Twine("_binary_") + SanitizedFilename;
126025d7b4fbSAlexey Lapshin 
126125d7b4fbSAlexey Lapshin   SymTab->addSymbol(Prefix + "_start", STB_GLOBAL, STT_NOTYPE, &DataSection,
126225d7b4fbSAlexey Lapshin                     /*Value=*/0, NewSymbolVisibility, 0, 0);
126325d7b4fbSAlexey Lapshin   SymTab->addSymbol(Prefix + "_end", STB_GLOBAL, STT_NOTYPE, &DataSection,
126425d7b4fbSAlexey Lapshin                     /*Value=*/DataSection.Size, NewSymbolVisibility, 0, 0);
126525d7b4fbSAlexey Lapshin   SymTab->addSymbol(Prefix + "_size", STB_GLOBAL, STT_NOTYPE, nullptr,
126625d7b4fbSAlexey Lapshin                     /*Value=*/DataSection.Size, NewSymbolVisibility, SHN_ABS,
126725d7b4fbSAlexey Lapshin                     0);
126825d7b4fbSAlexey Lapshin }
126925d7b4fbSAlexey Lapshin 
build()127025d7b4fbSAlexey Lapshin Expected<std::unique_ptr<Object>> BinaryELFBuilder::build() {
127125d7b4fbSAlexey Lapshin   initFileHeader();
127225d7b4fbSAlexey Lapshin   initHeaderSegment();
127325d7b4fbSAlexey Lapshin 
127425d7b4fbSAlexey Lapshin   SymbolTableSection *SymTab = addSymTab(addStrTab());
127525d7b4fbSAlexey Lapshin   if (Error Err = initSections())
127625d7b4fbSAlexey Lapshin     return std::move(Err);
127725d7b4fbSAlexey Lapshin   addData(SymTab);
127825d7b4fbSAlexey Lapshin 
127925d7b4fbSAlexey Lapshin   return std::move(Obj);
128025d7b4fbSAlexey Lapshin }
128125d7b4fbSAlexey Lapshin 
128225d7b4fbSAlexey Lapshin // Adds sections from IHEX data file. Data should have been
128325d7b4fbSAlexey Lapshin // fully validated by this time.
addDataSections()128425d7b4fbSAlexey Lapshin void IHexELFBuilder::addDataSections() {
128525d7b4fbSAlexey Lapshin   OwnedDataSection *Section = nullptr;
128625d7b4fbSAlexey Lapshin   uint64_t SegmentAddr = 0, BaseAddr = 0;
128725d7b4fbSAlexey Lapshin   uint32_t SecNo = 1;
128825d7b4fbSAlexey Lapshin 
128925d7b4fbSAlexey Lapshin   for (const IHexRecord &R : Records) {
129025d7b4fbSAlexey Lapshin     uint64_t RecAddr;
129125d7b4fbSAlexey Lapshin     switch (R.Type) {
129225d7b4fbSAlexey Lapshin     case IHexRecord::Data:
129325d7b4fbSAlexey Lapshin       // Ignore empty data records
129425d7b4fbSAlexey Lapshin       if (R.HexData.empty())
129525d7b4fbSAlexey Lapshin         continue;
129625d7b4fbSAlexey Lapshin       RecAddr = R.Addr + SegmentAddr + BaseAddr;
129725d7b4fbSAlexey Lapshin       if (!Section || Section->Addr + Section->Size != RecAddr) {
129825d7b4fbSAlexey Lapshin         // OriginalOffset field is only used to sort sections before layout, so
129925d7b4fbSAlexey Lapshin         // instead of keeping track of real offsets in IHEX file, and as
130025d7b4fbSAlexey Lapshin         // layoutSections() and layoutSectionsForOnlyKeepDebug() use
130125d7b4fbSAlexey Lapshin         // llvm::stable_sort(), we can just set it to a constant (zero).
130225d7b4fbSAlexey Lapshin         Section = &Obj->addSection<OwnedDataSection>(
130325d7b4fbSAlexey Lapshin             ".sec" + std::to_string(SecNo), RecAddr,
130425d7b4fbSAlexey Lapshin             ELF::SHF_ALLOC | ELF::SHF_WRITE, 0);
130525d7b4fbSAlexey Lapshin         SecNo++;
130625d7b4fbSAlexey Lapshin       }
130725d7b4fbSAlexey Lapshin       Section->appendHexData(R.HexData);
130825d7b4fbSAlexey Lapshin       break;
130925d7b4fbSAlexey Lapshin     case IHexRecord::EndOfFile:
131025d7b4fbSAlexey Lapshin       break;
131125d7b4fbSAlexey Lapshin     case IHexRecord::SegmentAddr:
131225d7b4fbSAlexey Lapshin       // 20-bit segment address.
131325d7b4fbSAlexey Lapshin       SegmentAddr = checkedGetHex<uint16_t>(R.HexData) << 4;
131425d7b4fbSAlexey Lapshin       break;
131525d7b4fbSAlexey Lapshin     case IHexRecord::StartAddr80x86:
131625d7b4fbSAlexey Lapshin     case IHexRecord::StartAddr:
131725d7b4fbSAlexey Lapshin       Obj->Entry = checkedGetHex<uint32_t>(R.HexData);
131825d7b4fbSAlexey Lapshin       assert(Obj->Entry <= 0xFFFFFU);
131925d7b4fbSAlexey Lapshin       break;
132025d7b4fbSAlexey Lapshin     case IHexRecord::ExtendedAddr:
132125d7b4fbSAlexey Lapshin       // 16-31 bits of linear base address
132225d7b4fbSAlexey Lapshin       BaseAddr = checkedGetHex<uint16_t>(R.HexData) << 16;
132325d7b4fbSAlexey Lapshin       break;
132425d7b4fbSAlexey Lapshin     default:
132525d7b4fbSAlexey Lapshin       llvm_unreachable("unknown record type");
132625d7b4fbSAlexey Lapshin     }
132725d7b4fbSAlexey Lapshin   }
132825d7b4fbSAlexey Lapshin }
132925d7b4fbSAlexey Lapshin 
build()133025d7b4fbSAlexey Lapshin Expected<std::unique_ptr<Object>> IHexELFBuilder::build() {
133125d7b4fbSAlexey Lapshin   initFileHeader();
133225d7b4fbSAlexey Lapshin   initHeaderSegment();
133325d7b4fbSAlexey Lapshin   StringTableSection *StrTab = addStrTab();
133425d7b4fbSAlexey Lapshin   addSymTab(StrTab);
133525d7b4fbSAlexey Lapshin   if (Error Err = initSections())
133625d7b4fbSAlexey Lapshin     return std::move(Err);
133725d7b4fbSAlexey Lapshin   addDataSections();
133825d7b4fbSAlexey Lapshin 
133925d7b4fbSAlexey Lapshin   return std::move(Obj);
134025d7b4fbSAlexey Lapshin }
134125d7b4fbSAlexey Lapshin 
134225d7b4fbSAlexey Lapshin template <class ELFT>
ELFBuilder(const ELFObjectFile<ELFT> & ElfObj,Object & Obj,Optional<StringRef> ExtractPartition)134325d7b4fbSAlexey Lapshin ELFBuilder<ELFT>::ELFBuilder(const ELFObjectFile<ELFT> &ElfObj, Object &Obj,
134425d7b4fbSAlexey Lapshin                              Optional<StringRef> ExtractPartition)
134525d7b4fbSAlexey Lapshin     : ElfFile(ElfObj.getELFFile()), Obj(Obj),
134625d7b4fbSAlexey Lapshin       ExtractPartition(ExtractPartition) {
134725d7b4fbSAlexey Lapshin   Obj.IsMips64EL = ElfFile.isMips64EL();
134825d7b4fbSAlexey Lapshin }
134925d7b4fbSAlexey Lapshin 
setParentSegment(Segment & Child)135025d7b4fbSAlexey Lapshin template <class ELFT> void ELFBuilder<ELFT>::setParentSegment(Segment &Child) {
135125d7b4fbSAlexey Lapshin   for (Segment &Parent : Obj.segments()) {
135225d7b4fbSAlexey Lapshin     // Every segment will overlap with itself but we don't want a segment to
135325d7b4fbSAlexey Lapshin     // be its own parent so we avoid that situation.
135425d7b4fbSAlexey Lapshin     if (&Child != &Parent && segmentOverlapsSegment(Child, Parent)) {
135525d7b4fbSAlexey Lapshin       // We want a canonical "most parental" segment but this requires
135625d7b4fbSAlexey Lapshin       // inspecting the ParentSegment.
135725d7b4fbSAlexey Lapshin       if (compareSegmentsByOffset(&Parent, &Child))
135825d7b4fbSAlexey Lapshin         if (Child.ParentSegment == nullptr ||
135925d7b4fbSAlexey Lapshin             compareSegmentsByOffset(&Parent, Child.ParentSegment)) {
136025d7b4fbSAlexey Lapshin           Child.ParentSegment = &Parent;
136125d7b4fbSAlexey Lapshin         }
136225d7b4fbSAlexey Lapshin     }
136325d7b4fbSAlexey Lapshin   }
136425d7b4fbSAlexey Lapshin }
136525d7b4fbSAlexey Lapshin 
findEhdrOffset()136625d7b4fbSAlexey Lapshin template <class ELFT> Error ELFBuilder<ELFT>::findEhdrOffset() {
136725d7b4fbSAlexey Lapshin   if (!ExtractPartition)
136825d7b4fbSAlexey Lapshin     return Error::success();
136925d7b4fbSAlexey Lapshin 
137025d7b4fbSAlexey Lapshin   for (const SectionBase &Sec : Obj.sections()) {
137125d7b4fbSAlexey Lapshin     if (Sec.Type == SHT_LLVM_PART_EHDR && Sec.Name == *ExtractPartition) {
137225d7b4fbSAlexey Lapshin       EhdrOffset = Sec.Offset;
137325d7b4fbSAlexey Lapshin       return Error::success();
137425d7b4fbSAlexey Lapshin     }
137525d7b4fbSAlexey Lapshin   }
137625d7b4fbSAlexey Lapshin   return createStringError(errc::invalid_argument,
137725d7b4fbSAlexey Lapshin                            "could not find partition named '" +
137825d7b4fbSAlexey Lapshin                                *ExtractPartition + "'");
137925d7b4fbSAlexey Lapshin }
138025d7b4fbSAlexey Lapshin 
138125d7b4fbSAlexey Lapshin template <class ELFT>
readProgramHeaders(const ELFFile<ELFT> & HeadersFile)138225d7b4fbSAlexey Lapshin Error ELFBuilder<ELFT>::readProgramHeaders(const ELFFile<ELFT> &HeadersFile) {
138325d7b4fbSAlexey Lapshin   uint32_t Index = 0;
138425d7b4fbSAlexey Lapshin 
138525d7b4fbSAlexey Lapshin   Expected<typename ELFFile<ELFT>::Elf_Phdr_Range> Headers =
138625d7b4fbSAlexey Lapshin       HeadersFile.program_headers();
138725d7b4fbSAlexey Lapshin   if (!Headers)
138825d7b4fbSAlexey Lapshin     return Headers.takeError();
138925d7b4fbSAlexey Lapshin 
139025d7b4fbSAlexey Lapshin   for (const typename ELFFile<ELFT>::Elf_Phdr &Phdr : *Headers) {
139125d7b4fbSAlexey Lapshin     if (Phdr.p_offset + Phdr.p_filesz > HeadersFile.getBufSize())
139225d7b4fbSAlexey Lapshin       return createStringError(
139325d7b4fbSAlexey Lapshin           errc::invalid_argument,
139425d7b4fbSAlexey Lapshin           "program header with offset 0x" + Twine::utohexstr(Phdr.p_offset) +
139525d7b4fbSAlexey Lapshin               " and file size 0x" + Twine::utohexstr(Phdr.p_filesz) +
139625d7b4fbSAlexey Lapshin               " goes past the end of the file");
139725d7b4fbSAlexey Lapshin 
139825d7b4fbSAlexey Lapshin     ArrayRef<uint8_t> Data{HeadersFile.base() + Phdr.p_offset,
139925d7b4fbSAlexey Lapshin                            (size_t)Phdr.p_filesz};
140025d7b4fbSAlexey Lapshin     Segment &Seg = Obj.addSegment(Data);
140125d7b4fbSAlexey Lapshin     Seg.Type = Phdr.p_type;
140225d7b4fbSAlexey Lapshin     Seg.Flags = Phdr.p_flags;
140325d7b4fbSAlexey Lapshin     Seg.OriginalOffset = Phdr.p_offset + EhdrOffset;
140425d7b4fbSAlexey Lapshin     Seg.Offset = Phdr.p_offset + EhdrOffset;
140525d7b4fbSAlexey Lapshin     Seg.VAddr = Phdr.p_vaddr;
140625d7b4fbSAlexey Lapshin     Seg.PAddr = Phdr.p_paddr;
140725d7b4fbSAlexey Lapshin     Seg.FileSize = Phdr.p_filesz;
140825d7b4fbSAlexey Lapshin     Seg.MemSize = Phdr.p_memsz;
140925d7b4fbSAlexey Lapshin     Seg.Align = Phdr.p_align;
141025d7b4fbSAlexey Lapshin     Seg.Index = Index++;
141125d7b4fbSAlexey Lapshin     for (SectionBase &Sec : Obj.sections())
141225d7b4fbSAlexey Lapshin       if (sectionWithinSegment(Sec, Seg)) {
141325d7b4fbSAlexey Lapshin         Seg.addSection(&Sec);
141425d7b4fbSAlexey Lapshin         if (!Sec.ParentSegment || Sec.ParentSegment->Offset > Seg.Offset)
141525d7b4fbSAlexey Lapshin           Sec.ParentSegment = &Seg;
141625d7b4fbSAlexey Lapshin       }
141725d7b4fbSAlexey Lapshin   }
141825d7b4fbSAlexey Lapshin 
141925d7b4fbSAlexey Lapshin   auto &ElfHdr = Obj.ElfHdrSegment;
142025d7b4fbSAlexey Lapshin   ElfHdr.Index = Index++;
142125d7b4fbSAlexey Lapshin   ElfHdr.OriginalOffset = ElfHdr.Offset = EhdrOffset;
142225d7b4fbSAlexey Lapshin 
142325d7b4fbSAlexey Lapshin   const typename ELFT::Ehdr &Ehdr = HeadersFile.getHeader();
142425d7b4fbSAlexey Lapshin   auto &PrHdr = Obj.ProgramHdrSegment;
142525d7b4fbSAlexey Lapshin   PrHdr.Type = PT_PHDR;
142625d7b4fbSAlexey Lapshin   PrHdr.Flags = 0;
142725d7b4fbSAlexey Lapshin   // The spec requires us to have p_vaddr % p_align == p_offset % p_align.
142825d7b4fbSAlexey Lapshin   // Whereas this works automatically for ElfHdr, here OriginalOffset is
142925d7b4fbSAlexey Lapshin   // always non-zero and to ensure the equation we assign the same value to
143025d7b4fbSAlexey Lapshin   // VAddr as well.
143125d7b4fbSAlexey Lapshin   PrHdr.OriginalOffset = PrHdr.Offset = PrHdr.VAddr = EhdrOffset + Ehdr.e_phoff;
143225d7b4fbSAlexey Lapshin   PrHdr.PAddr = 0;
143325d7b4fbSAlexey Lapshin   PrHdr.FileSize = PrHdr.MemSize = Ehdr.e_phentsize * Ehdr.e_phnum;
143425d7b4fbSAlexey Lapshin   // The spec requires us to naturally align all the fields.
143525d7b4fbSAlexey Lapshin   PrHdr.Align = sizeof(Elf_Addr);
143625d7b4fbSAlexey Lapshin   PrHdr.Index = Index++;
143725d7b4fbSAlexey Lapshin 
143825d7b4fbSAlexey Lapshin   // Now we do an O(n^2) loop through the segments in order to match up
143925d7b4fbSAlexey Lapshin   // segments.
144025d7b4fbSAlexey Lapshin   for (Segment &Child : Obj.segments())
144125d7b4fbSAlexey Lapshin     setParentSegment(Child);
144225d7b4fbSAlexey Lapshin   setParentSegment(ElfHdr);
144325d7b4fbSAlexey Lapshin   setParentSegment(PrHdr);
144425d7b4fbSAlexey Lapshin 
144525d7b4fbSAlexey Lapshin   return Error::success();
144625d7b4fbSAlexey Lapshin }
144725d7b4fbSAlexey Lapshin 
144825d7b4fbSAlexey Lapshin template <class ELFT>
initGroupSection(GroupSection * GroupSec)144925d7b4fbSAlexey Lapshin Error ELFBuilder<ELFT>::initGroupSection(GroupSection *GroupSec) {
145025d7b4fbSAlexey Lapshin   if (GroupSec->Align % sizeof(ELF::Elf32_Word) != 0)
145125d7b4fbSAlexey Lapshin     return createStringError(errc::invalid_argument,
145225d7b4fbSAlexey Lapshin                              "invalid alignment " + Twine(GroupSec->Align) +
145325d7b4fbSAlexey Lapshin                                  " of group section '" + GroupSec->Name + "'");
145425d7b4fbSAlexey Lapshin   SectionTableRef SecTable = Obj.sections();
145525d7b4fbSAlexey Lapshin   if (GroupSec->Link != SHN_UNDEF) {
145625d7b4fbSAlexey Lapshin     auto SymTab = SecTable.template getSectionOfType<SymbolTableSection>(
145725d7b4fbSAlexey Lapshin         GroupSec->Link,
145825d7b4fbSAlexey Lapshin         "link field value '" + Twine(GroupSec->Link) + "' in section '" +
145925d7b4fbSAlexey Lapshin             GroupSec->Name + "' is invalid",
146025d7b4fbSAlexey Lapshin         "link field value '" + Twine(GroupSec->Link) + "' in section '" +
146125d7b4fbSAlexey Lapshin             GroupSec->Name + "' is not a symbol table");
146225d7b4fbSAlexey Lapshin     if (!SymTab)
146325d7b4fbSAlexey Lapshin       return SymTab.takeError();
146425d7b4fbSAlexey Lapshin 
146525d7b4fbSAlexey Lapshin     Expected<Symbol *> Sym = (*SymTab)->getSymbolByIndex(GroupSec->Info);
146625d7b4fbSAlexey Lapshin     if (!Sym)
146725d7b4fbSAlexey Lapshin       return createStringError(errc::invalid_argument,
146825d7b4fbSAlexey Lapshin                                "info field value '" + Twine(GroupSec->Info) +
146925d7b4fbSAlexey Lapshin                                    "' in section '" + GroupSec->Name +
147025d7b4fbSAlexey Lapshin                                    "' is not a valid symbol index");
147125d7b4fbSAlexey Lapshin     GroupSec->setSymTab(*SymTab);
147225d7b4fbSAlexey Lapshin     GroupSec->setSymbol(*Sym);
147325d7b4fbSAlexey Lapshin   }
147425d7b4fbSAlexey Lapshin   if (GroupSec->Contents.size() % sizeof(ELF::Elf32_Word) ||
147525d7b4fbSAlexey Lapshin       GroupSec->Contents.empty())
147625d7b4fbSAlexey Lapshin     return createStringError(errc::invalid_argument,
147725d7b4fbSAlexey Lapshin                              "the content of the section " + GroupSec->Name +
147825d7b4fbSAlexey Lapshin                                  " is malformed");
147925d7b4fbSAlexey Lapshin   const ELF::Elf32_Word *Word =
148025d7b4fbSAlexey Lapshin       reinterpret_cast<const ELF::Elf32_Word *>(GroupSec->Contents.data());
148125d7b4fbSAlexey Lapshin   const ELF::Elf32_Word *End =
148225d7b4fbSAlexey Lapshin       Word + GroupSec->Contents.size() / sizeof(ELF::Elf32_Word);
148325d7b4fbSAlexey Lapshin   GroupSec->setFlagWord(
148425d7b4fbSAlexey Lapshin       support::endian::read32<ELFT::TargetEndianness>(Word++));
148525d7b4fbSAlexey Lapshin   for (; Word != End; ++Word) {
148625d7b4fbSAlexey Lapshin     uint32_t Index = support::endian::read32<ELFT::TargetEndianness>(Word);
148725d7b4fbSAlexey Lapshin     Expected<SectionBase *> Sec = SecTable.getSection(
148825d7b4fbSAlexey Lapshin         Index, "group member index " + Twine(Index) + " in section '" +
148925d7b4fbSAlexey Lapshin                    GroupSec->Name + "' is invalid");
149025d7b4fbSAlexey Lapshin     if (!Sec)
149125d7b4fbSAlexey Lapshin       return Sec.takeError();
149225d7b4fbSAlexey Lapshin 
149325d7b4fbSAlexey Lapshin     GroupSec->addMember(*Sec);
149425d7b4fbSAlexey Lapshin   }
149525d7b4fbSAlexey Lapshin 
149625d7b4fbSAlexey Lapshin   return Error::success();
149725d7b4fbSAlexey Lapshin }
149825d7b4fbSAlexey Lapshin 
149925d7b4fbSAlexey Lapshin template <class ELFT>
initSymbolTable(SymbolTableSection * SymTab)150025d7b4fbSAlexey Lapshin Error ELFBuilder<ELFT>::initSymbolTable(SymbolTableSection *SymTab) {
150125d7b4fbSAlexey Lapshin   Expected<const Elf_Shdr *> Shdr = ElfFile.getSection(SymTab->Index);
150225d7b4fbSAlexey Lapshin   if (!Shdr)
150325d7b4fbSAlexey Lapshin     return Shdr.takeError();
150425d7b4fbSAlexey Lapshin 
150525d7b4fbSAlexey Lapshin   Expected<StringRef> StrTabData = ElfFile.getStringTableForSymtab(**Shdr);
150625d7b4fbSAlexey Lapshin   if (!StrTabData)
150725d7b4fbSAlexey Lapshin     return StrTabData.takeError();
150825d7b4fbSAlexey Lapshin 
150925d7b4fbSAlexey Lapshin   ArrayRef<Elf_Word> ShndxData;
151025d7b4fbSAlexey Lapshin 
151125d7b4fbSAlexey Lapshin   Expected<typename ELFFile<ELFT>::Elf_Sym_Range> Symbols =
151225d7b4fbSAlexey Lapshin       ElfFile.symbols(*Shdr);
151325d7b4fbSAlexey Lapshin   if (!Symbols)
151425d7b4fbSAlexey Lapshin     return Symbols.takeError();
151525d7b4fbSAlexey Lapshin 
151625d7b4fbSAlexey Lapshin   for (const typename ELFFile<ELFT>::Elf_Sym &Sym : *Symbols) {
151725d7b4fbSAlexey Lapshin     SectionBase *DefSection = nullptr;
151825d7b4fbSAlexey Lapshin 
151925d7b4fbSAlexey Lapshin     Expected<StringRef> Name = Sym.getName(*StrTabData);
152025d7b4fbSAlexey Lapshin     if (!Name)
152125d7b4fbSAlexey Lapshin       return Name.takeError();
152225d7b4fbSAlexey Lapshin 
152325d7b4fbSAlexey Lapshin     if (Sym.st_shndx == SHN_XINDEX) {
152425d7b4fbSAlexey Lapshin       if (SymTab->getShndxTable() == nullptr)
152525d7b4fbSAlexey Lapshin         return createStringError(errc::invalid_argument,
152625d7b4fbSAlexey Lapshin                                  "symbol '" + *Name +
152725d7b4fbSAlexey Lapshin                                      "' has index SHN_XINDEX but no "
152825d7b4fbSAlexey Lapshin                                      "SHT_SYMTAB_SHNDX section exists");
152925d7b4fbSAlexey Lapshin       if (ShndxData.data() == nullptr) {
153025d7b4fbSAlexey Lapshin         Expected<const Elf_Shdr *> ShndxSec =
153125d7b4fbSAlexey Lapshin             ElfFile.getSection(SymTab->getShndxTable()->Index);
153225d7b4fbSAlexey Lapshin         if (!ShndxSec)
153325d7b4fbSAlexey Lapshin           return ShndxSec.takeError();
153425d7b4fbSAlexey Lapshin 
153525d7b4fbSAlexey Lapshin         Expected<ArrayRef<Elf_Word>> Data =
153625d7b4fbSAlexey Lapshin             ElfFile.template getSectionContentsAsArray<Elf_Word>(**ShndxSec);
153725d7b4fbSAlexey Lapshin         if (!Data)
153825d7b4fbSAlexey Lapshin           return Data.takeError();
153925d7b4fbSAlexey Lapshin 
154025d7b4fbSAlexey Lapshin         ShndxData = *Data;
154125d7b4fbSAlexey Lapshin         if (ShndxData.size() != Symbols->size())
154225d7b4fbSAlexey Lapshin           return createStringError(
154325d7b4fbSAlexey Lapshin               errc::invalid_argument,
154425d7b4fbSAlexey Lapshin               "symbol section index table does not have the same number of "
154525d7b4fbSAlexey Lapshin               "entries as the symbol table");
154625d7b4fbSAlexey Lapshin       }
154725d7b4fbSAlexey Lapshin       Elf_Word Index = ShndxData[&Sym - Symbols->begin()];
154825d7b4fbSAlexey Lapshin       Expected<SectionBase *> Sec = Obj.sections().getSection(
154925d7b4fbSAlexey Lapshin           Index,
155025d7b4fbSAlexey Lapshin           "symbol '" + *Name + "' has invalid section index " + Twine(Index));
155125d7b4fbSAlexey Lapshin       if (!Sec)
155225d7b4fbSAlexey Lapshin         return Sec.takeError();
155325d7b4fbSAlexey Lapshin 
155425d7b4fbSAlexey Lapshin       DefSection = *Sec;
155525d7b4fbSAlexey Lapshin     } else if (Sym.st_shndx >= SHN_LORESERVE) {
155625d7b4fbSAlexey Lapshin       if (!isValidReservedSectionIndex(Sym.st_shndx, Obj.Machine)) {
155725d7b4fbSAlexey Lapshin         return createStringError(
155825d7b4fbSAlexey Lapshin             errc::invalid_argument,
155925d7b4fbSAlexey Lapshin             "symbol '" + *Name +
156025d7b4fbSAlexey Lapshin                 "' has unsupported value greater than or equal "
156125d7b4fbSAlexey Lapshin                 "to SHN_LORESERVE: " +
156225d7b4fbSAlexey Lapshin                 Twine(Sym.st_shndx));
156325d7b4fbSAlexey Lapshin       }
156425d7b4fbSAlexey Lapshin     } else if (Sym.st_shndx != SHN_UNDEF) {
156525d7b4fbSAlexey Lapshin       Expected<SectionBase *> Sec = Obj.sections().getSection(
156625d7b4fbSAlexey Lapshin           Sym.st_shndx, "symbol '" + *Name +
156725d7b4fbSAlexey Lapshin                             "' is defined has invalid section index " +
156825d7b4fbSAlexey Lapshin                             Twine(Sym.st_shndx));
156925d7b4fbSAlexey Lapshin       if (!Sec)
157025d7b4fbSAlexey Lapshin         return Sec.takeError();
157125d7b4fbSAlexey Lapshin 
157225d7b4fbSAlexey Lapshin       DefSection = *Sec;
157325d7b4fbSAlexey Lapshin     }
157425d7b4fbSAlexey Lapshin 
157525d7b4fbSAlexey Lapshin     SymTab->addSymbol(*Name, Sym.getBinding(), Sym.getType(), DefSection,
157625d7b4fbSAlexey Lapshin                       Sym.getValue(), Sym.st_other, Sym.st_shndx, Sym.st_size);
157725d7b4fbSAlexey Lapshin   }
157825d7b4fbSAlexey Lapshin 
157925d7b4fbSAlexey Lapshin   return Error::success();
158025d7b4fbSAlexey Lapshin }
158125d7b4fbSAlexey Lapshin 
158225d7b4fbSAlexey Lapshin template <class ELFT>
getAddend(uint64_t &,const Elf_Rel_Impl<ELFT,false> &)158325d7b4fbSAlexey Lapshin static void getAddend(uint64_t &, const Elf_Rel_Impl<ELFT, false> &) {}
158425d7b4fbSAlexey Lapshin 
158525d7b4fbSAlexey Lapshin template <class ELFT>
getAddend(uint64_t & ToSet,const Elf_Rel_Impl<ELFT,true> & Rela)158625d7b4fbSAlexey Lapshin static void getAddend(uint64_t &ToSet, const Elf_Rel_Impl<ELFT, true> &Rela) {
158725d7b4fbSAlexey Lapshin   ToSet = Rela.r_addend;
158825d7b4fbSAlexey Lapshin }
158925d7b4fbSAlexey Lapshin 
159025d7b4fbSAlexey Lapshin template <class T>
initRelocations(RelocationSection * Relocs,T RelRange)159125d7b4fbSAlexey Lapshin static Error initRelocations(RelocationSection *Relocs, T RelRange) {
159225d7b4fbSAlexey Lapshin   for (const auto &Rel : RelRange) {
159325d7b4fbSAlexey Lapshin     Relocation ToAdd;
159425d7b4fbSAlexey Lapshin     ToAdd.Offset = Rel.r_offset;
159525d7b4fbSAlexey Lapshin     getAddend(ToAdd.Addend, Rel);
159625d7b4fbSAlexey Lapshin     ToAdd.Type = Rel.getType(Relocs->getObject().IsMips64EL);
159725d7b4fbSAlexey Lapshin 
159825d7b4fbSAlexey Lapshin     if (uint32_t Sym = Rel.getSymbol(Relocs->getObject().IsMips64EL)) {
159925d7b4fbSAlexey Lapshin       if (!Relocs->getObject().SymbolTable)
160025d7b4fbSAlexey Lapshin         return createStringError(
160125d7b4fbSAlexey Lapshin             errc::invalid_argument,
160225d7b4fbSAlexey Lapshin             "'" + Relocs->Name + "': relocation references symbol with index " +
160325d7b4fbSAlexey Lapshin                 Twine(Sym) + ", but there is no symbol table");
160425d7b4fbSAlexey Lapshin       Expected<Symbol *> SymByIndex =
160525d7b4fbSAlexey Lapshin           Relocs->getObject().SymbolTable->getSymbolByIndex(Sym);
160625d7b4fbSAlexey Lapshin       if (!SymByIndex)
160725d7b4fbSAlexey Lapshin         return SymByIndex.takeError();
160825d7b4fbSAlexey Lapshin 
160925d7b4fbSAlexey Lapshin       ToAdd.RelocSymbol = *SymByIndex;
161025d7b4fbSAlexey Lapshin     }
161125d7b4fbSAlexey Lapshin 
161225d7b4fbSAlexey Lapshin     Relocs->addRelocation(ToAdd);
161325d7b4fbSAlexey Lapshin   }
161425d7b4fbSAlexey Lapshin 
161525d7b4fbSAlexey Lapshin   return Error::success();
161625d7b4fbSAlexey Lapshin }
161725d7b4fbSAlexey Lapshin 
getSection(uint32_t Index,Twine ErrMsg)161825d7b4fbSAlexey Lapshin Expected<SectionBase *> SectionTableRef::getSection(uint32_t Index,
161925d7b4fbSAlexey Lapshin                                                     Twine ErrMsg) {
162025d7b4fbSAlexey Lapshin   if (Index == SHN_UNDEF || Index > Sections.size())
162125d7b4fbSAlexey Lapshin     return createStringError(errc::invalid_argument, ErrMsg);
162225d7b4fbSAlexey Lapshin   return Sections[Index - 1].get();
162325d7b4fbSAlexey Lapshin }
162425d7b4fbSAlexey Lapshin 
162525d7b4fbSAlexey Lapshin template <class T>
getSectionOfType(uint32_t Index,Twine IndexErrMsg,Twine TypeErrMsg)162625d7b4fbSAlexey Lapshin Expected<T *> SectionTableRef::getSectionOfType(uint32_t Index,
162725d7b4fbSAlexey Lapshin                                                 Twine IndexErrMsg,
162825d7b4fbSAlexey Lapshin                                                 Twine TypeErrMsg) {
162925d7b4fbSAlexey Lapshin   Expected<SectionBase *> BaseSec = getSection(Index, IndexErrMsg);
163025d7b4fbSAlexey Lapshin   if (!BaseSec)
163125d7b4fbSAlexey Lapshin     return BaseSec.takeError();
163225d7b4fbSAlexey Lapshin 
163325d7b4fbSAlexey Lapshin   if (T *Sec = dyn_cast<T>(*BaseSec))
163425d7b4fbSAlexey Lapshin     return Sec;
163525d7b4fbSAlexey Lapshin 
163625d7b4fbSAlexey Lapshin   return createStringError(errc::invalid_argument, TypeErrMsg);
163725d7b4fbSAlexey Lapshin }
163825d7b4fbSAlexey Lapshin 
163925d7b4fbSAlexey Lapshin template <class ELFT>
makeSection(const Elf_Shdr & Shdr)164025d7b4fbSAlexey Lapshin Expected<SectionBase &> ELFBuilder<ELFT>::makeSection(const Elf_Shdr &Shdr) {
164125d7b4fbSAlexey Lapshin   switch (Shdr.sh_type) {
164225d7b4fbSAlexey Lapshin   case SHT_REL:
164325d7b4fbSAlexey Lapshin   case SHT_RELA:
164425d7b4fbSAlexey Lapshin     if (Shdr.sh_flags & SHF_ALLOC) {
164525d7b4fbSAlexey Lapshin       if (Expected<ArrayRef<uint8_t>> Data = ElfFile.getSectionContents(Shdr))
164625d7b4fbSAlexey Lapshin         return Obj.addSection<DynamicRelocationSection>(*Data);
164725d7b4fbSAlexey Lapshin       else
164825d7b4fbSAlexey Lapshin         return Data.takeError();
164925d7b4fbSAlexey Lapshin     }
165025d7b4fbSAlexey Lapshin     return Obj.addSection<RelocationSection>(Obj);
165125d7b4fbSAlexey Lapshin   case SHT_STRTAB:
165225d7b4fbSAlexey Lapshin     // If a string table is allocated we don't want to mess with it. That would
165325d7b4fbSAlexey Lapshin     // mean altering the memory image. There are no special link types or
165425d7b4fbSAlexey Lapshin     // anything so we can just use a Section.
165525d7b4fbSAlexey Lapshin     if (Shdr.sh_flags & SHF_ALLOC) {
165625d7b4fbSAlexey Lapshin       if (Expected<ArrayRef<uint8_t>> Data = ElfFile.getSectionContents(Shdr))
165725d7b4fbSAlexey Lapshin         return Obj.addSection<Section>(*Data);
165825d7b4fbSAlexey Lapshin       else
165925d7b4fbSAlexey Lapshin         return Data.takeError();
166025d7b4fbSAlexey Lapshin     }
166125d7b4fbSAlexey Lapshin     return Obj.addSection<StringTableSection>();
166225d7b4fbSAlexey Lapshin   case SHT_HASH:
166325d7b4fbSAlexey Lapshin   case SHT_GNU_HASH:
166425d7b4fbSAlexey Lapshin     // Hash tables should refer to SHT_DYNSYM which we're not going to change.
166525d7b4fbSAlexey Lapshin     // Because of this we don't need to mess with the hash tables either.
166625d7b4fbSAlexey Lapshin     if (Expected<ArrayRef<uint8_t>> Data = ElfFile.getSectionContents(Shdr))
166725d7b4fbSAlexey Lapshin       return Obj.addSection<Section>(*Data);
166825d7b4fbSAlexey Lapshin     else
166925d7b4fbSAlexey Lapshin       return Data.takeError();
167025d7b4fbSAlexey Lapshin   case SHT_GROUP:
167125d7b4fbSAlexey Lapshin     if (Expected<ArrayRef<uint8_t>> Data = ElfFile.getSectionContents(Shdr))
167225d7b4fbSAlexey Lapshin       return Obj.addSection<GroupSection>(*Data);
167325d7b4fbSAlexey Lapshin     else
167425d7b4fbSAlexey Lapshin       return Data.takeError();
167525d7b4fbSAlexey Lapshin   case SHT_DYNSYM:
167625d7b4fbSAlexey Lapshin     if (Expected<ArrayRef<uint8_t>> Data = ElfFile.getSectionContents(Shdr))
167725d7b4fbSAlexey Lapshin       return Obj.addSection<DynamicSymbolTableSection>(*Data);
167825d7b4fbSAlexey Lapshin     else
167925d7b4fbSAlexey Lapshin       return Data.takeError();
168025d7b4fbSAlexey Lapshin   case SHT_DYNAMIC:
168125d7b4fbSAlexey Lapshin     if (Expected<ArrayRef<uint8_t>> Data = ElfFile.getSectionContents(Shdr))
168225d7b4fbSAlexey Lapshin       return Obj.addSection<DynamicSection>(*Data);
168325d7b4fbSAlexey Lapshin     else
168425d7b4fbSAlexey Lapshin       return Data.takeError();
168525d7b4fbSAlexey Lapshin   case SHT_SYMTAB: {
168625d7b4fbSAlexey Lapshin     auto &SymTab = Obj.addSection<SymbolTableSection>();
168725d7b4fbSAlexey Lapshin     Obj.SymbolTable = &SymTab;
168825d7b4fbSAlexey Lapshin     return SymTab;
168925d7b4fbSAlexey Lapshin   }
169025d7b4fbSAlexey Lapshin   case SHT_SYMTAB_SHNDX: {
169125d7b4fbSAlexey Lapshin     auto &ShndxSection = Obj.addSection<SectionIndexSection>();
169225d7b4fbSAlexey Lapshin     Obj.SectionIndexTable = &ShndxSection;
169325d7b4fbSAlexey Lapshin     return ShndxSection;
169425d7b4fbSAlexey Lapshin   }
169525d7b4fbSAlexey Lapshin   case SHT_NOBITS:
169625d7b4fbSAlexey Lapshin     return Obj.addSection<Section>(ArrayRef<uint8_t>());
169725d7b4fbSAlexey Lapshin   default: {
169825d7b4fbSAlexey Lapshin     Expected<ArrayRef<uint8_t>> Data = ElfFile.getSectionContents(Shdr);
169925d7b4fbSAlexey Lapshin     if (!Data)
170025d7b4fbSAlexey Lapshin       return Data.takeError();
170125d7b4fbSAlexey Lapshin 
170225d7b4fbSAlexey Lapshin     Expected<StringRef> Name = ElfFile.getSectionName(Shdr);
170325d7b4fbSAlexey Lapshin     if (!Name)
170425d7b4fbSAlexey Lapshin       return Name.takeError();
170525d7b4fbSAlexey Lapshin 
1706*91e2cd4fSFangrui Song     if (!(Shdr.sh_flags & ELF::SHF_COMPRESSED))
170725d7b4fbSAlexey Lapshin       return Obj.addSection<Section>(*Data);
1708*91e2cd4fSFangrui Song     auto *Chdr = reinterpret_cast<const Elf_Chdr_Impl<ELFT> *>(Data->data());
1709*91e2cd4fSFangrui Song     return Obj.addSection<CompressedSection>(
1710*91e2cd4fSFangrui Song         CompressedSection(*Data, Chdr->ch_size, Chdr->ch_addralign));
171125d7b4fbSAlexey Lapshin   }
171225d7b4fbSAlexey Lapshin   }
171325d7b4fbSAlexey Lapshin }
171425d7b4fbSAlexey Lapshin 
readSectionHeaders()171525d7b4fbSAlexey Lapshin template <class ELFT> Error ELFBuilder<ELFT>::readSectionHeaders() {
171625d7b4fbSAlexey Lapshin   uint32_t Index = 0;
171725d7b4fbSAlexey Lapshin   Expected<typename ELFFile<ELFT>::Elf_Shdr_Range> Sections =
171825d7b4fbSAlexey Lapshin       ElfFile.sections();
171925d7b4fbSAlexey Lapshin   if (!Sections)
172025d7b4fbSAlexey Lapshin     return Sections.takeError();
172125d7b4fbSAlexey Lapshin 
172225d7b4fbSAlexey Lapshin   for (const typename ELFFile<ELFT>::Elf_Shdr &Shdr : *Sections) {
172325d7b4fbSAlexey Lapshin     if (Index == 0) {
172425d7b4fbSAlexey Lapshin       ++Index;
172525d7b4fbSAlexey Lapshin       continue;
172625d7b4fbSAlexey Lapshin     }
172725d7b4fbSAlexey Lapshin     Expected<SectionBase &> Sec = makeSection(Shdr);
172825d7b4fbSAlexey Lapshin     if (!Sec)
172925d7b4fbSAlexey Lapshin       return Sec.takeError();
173025d7b4fbSAlexey Lapshin 
173125d7b4fbSAlexey Lapshin     Expected<StringRef> SecName = ElfFile.getSectionName(Shdr);
173225d7b4fbSAlexey Lapshin     if (!SecName)
173325d7b4fbSAlexey Lapshin       return SecName.takeError();
173425d7b4fbSAlexey Lapshin     Sec->Name = SecName->str();
173525d7b4fbSAlexey Lapshin     Sec->Type = Sec->OriginalType = Shdr.sh_type;
173625d7b4fbSAlexey Lapshin     Sec->Flags = Sec->OriginalFlags = Shdr.sh_flags;
173725d7b4fbSAlexey Lapshin     Sec->Addr = Shdr.sh_addr;
173825d7b4fbSAlexey Lapshin     Sec->Offset = Shdr.sh_offset;
173925d7b4fbSAlexey Lapshin     Sec->OriginalOffset = Shdr.sh_offset;
174025d7b4fbSAlexey Lapshin     Sec->Size = Shdr.sh_size;
174125d7b4fbSAlexey Lapshin     Sec->Link = Shdr.sh_link;
174225d7b4fbSAlexey Lapshin     Sec->Info = Shdr.sh_info;
174325d7b4fbSAlexey Lapshin     Sec->Align = Shdr.sh_addralign;
174425d7b4fbSAlexey Lapshin     Sec->EntrySize = Shdr.sh_entsize;
174525d7b4fbSAlexey Lapshin     Sec->Index = Index++;
174625d7b4fbSAlexey Lapshin     Sec->OriginalIndex = Sec->Index;
174725d7b4fbSAlexey Lapshin     Sec->OriginalData = ArrayRef<uint8_t>(
174825d7b4fbSAlexey Lapshin         ElfFile.base() + Shdr.sh_offset,
174925d7b4fbSAlexey Lapshin         (Shdr.sh_type == SHT_NOBITS) ? (size_t)0 : Shdr.sh_size);
175025d7b4fbSAlexey Lapshin   }
175125d7b4fbSAlexey Lapshin 
175225d7b4fbSAlexey Lapshin   return Error::success();
175325d7b4fbSAlexey Lapshin }
175425d7b4fbSAlexey Lapshin 
readSections(bool EnsureSymtab)175525d7b4fbSAlexey Lapshin template <class ELFT> Error ELFBuilder<ELFT>::readSections(bool EnsureSymtab) {
175625d7b4fbSAlexey Lapshin   uint32_t ShstrIndex = ElfFile.getHeader().e_shstrndx;
175725d7b4fbSAlexey Lapshin   if (ShstrIndex == SHN_XINDEX) {
175825d7b4fbSAlexey Lapshin     Expected<const Elf_Shdr *> Sec = ElfFile.getSection(0);
175925d7b4fbSAlexey Lapshin     if (!Sec)
176025d7b4fbSAlexey Lapshin       return Sec.takeError();
176125d7b4fbSAlexey Lapshin 
176225d7b4fbSAlexey Lapshin     ShstrIndex = (*Sec)->sh_link;
176325d7b4fbSAlexey Lapshin   }
176425d7b4fbSAlexey Lapshin 
176525d7b4fbSAlexey Lapshin   if (ShstrIndex == SHN_UNDEF)
176625d7b4fbSAlexey Lapshin     Obj.HadShdrs = false;
176725d7b4fbSAlexey Lapshin   else {
176825d7b4fbSAlexey Lapshin     Expected<StringTableSection *> Sec =
176925d7b4fbSAlexey Lapshin         Obj.sections().template getSectionOfType<StringTableSection>(
177025d7b4fbSAlexey Lapshin             ShstrIndex,
177125d7b4fbSAlexey Lapshin             "e_shstrndx field value " + Twine(ShstrIndex) + " in elf header " +
177225d7b4fbSAlexey Lapshin                 " is invalid",
177325d7b4fbSAlexey Lapshin             "e_shstrndx field value " + Twine(ShstrIndex) + " in elf header " +
177425d7b4fbSAlexey Lapshin                 " does not reference a string table");
177525d7b4fbSAlexey Lapshin     if (!Sec)
177625d7b4fbSAlexey Lapshin       return Sec.takeError();
177725d7b4fbSAlexey Lapshin 
177825d7b4fbSAlexey Lapshin     Obj.SectionNames = *Sec;
177925d7b4fbSAlexey Lapshin   }
178025d7b4fbSAlexey Lapshin 
178125d7b4fbSAlexey Lapshin   // If a section index table exists we'll need to initialize it before we
178225d7b4fbSAlexey Lapshin   // initialize the symbol table because the symbol table might need to
178325d7b4fbSAlexey Lapshin   // reference it.
178425d7b4fbSAlexey Lapshin   if (Obj.SectionIndexTable)
178525d7b4fbSAlexey Lapshin     if (Error Err = Obj.SectionIndexTable->initialize(Obj.sections()))
178625d7b4fbSAlexey Lapshin       return Err;
178725d7b4fbSAlexey Lapshin 
178825d7b4fbSAlexey Lapshin   // Now that all of the sections have been added we can fill out some extra
178925d7b4fbSAlexey Lapshin   // details about symbol tables. We need the symbol table filled out before
179025d7b4fbSAlexey Lapshin   // any relocations.
179125d7b4fbSAlexey Lapshin   if (Obj.SymbolTable) {
179225d7b4fbSAlexey Lapshin     if (Error Err = Obj.SymbolTable->initialize(Obj.sections()))
179325d7b4fbSAlexey Lapshin       return Err;
179425d7b4fbSAlexey Lapshin     if (Error Err = initSymbolTable(Obj.SymbolTable))
179525d7b4fbSAlexey Lapshin       return Err;
179625d7b4fbSAlexey Lapshin   } else if (EnsureSymtab) {
179725d7b4fbSAlexey Lapshin     if (Error Err = Obj.addNewSymbolTable())
179825d7b4fbSAlexey Lapshin       return Err;
179925d7b4fbSAlexey Lapshin   }
180025d7b4fbSAlexey Lapshin 
180125d7b4fbSAlexey Lapshin   // Now that all sections and symbols have been added we can add
180225d7b4fbSAlexey Lapshin   // relocations that reference symbols and set the link and info fields for
180325d7b4fbSAlexey Lapshin   // relocation sections.
180425d7b4fbSAlexey Lapshin   for (SectionBase &Sec : Obj.sections()) {
180525d7b4fbSAlexey Lapshin     if (&Sec == Obj.SymbolTable)
180625d7b4fbSAlexey Lapshin       continue;
180725d7b4fbSAlexey Lapshin     if (Error Err = Sec.initialize(Obj.sections()))
180825d7b4fbSAlexey Lapshin       return Err;
180925d7b4fbSAlexey Lapshin     if (auto RelSec = dyn_cast<RelocationSection>(&Sec)) {
181025d7b4fbSAlexey Lapshin       Expected<typename ELFFile<ELFT>::Elf_Shdr_Range> Sections =
181125d7b4fbSAlexey Lapshin           ElfFile.sections();
181225d7b4fbSAlexey Lapshin       if (!Sections)
181325d7b4fbSAlexey Lapshin         return Sections.takeError();
181425d7b4fbSAlexey Lapshin 
181525d7b4fbSAlexey Lapshin       const typename ELFFile<ELFT>::Elf_Shdr *Shdr =
181625d7b4fbSAlexey Lapshin           Sections->begin() + RelSec->Index;
181725d7b4fbSAlexey Lapshin       if (RelSec->Type == SHT_REL) {
181825d7b4fbSAlexey Lapshin         Expected<typename ELFFile<ELFT>::Elf_Rel_Range> Rels =
181925d7b4fbSAlexey Lapshin             ElfFile.rels(*Shdr);
182025d7b4fbSAlexey Lapshin         if (!Rels)
182125d7b4fbSAlexey Lapshin           return Rels.takeError();
182225d7b4fbSAlexey Lapshin 
182325d7b4fbSAlexey Lapshin         if (Error Err = initRelocations(RelSec, *Rels))
182425d7b4fbSAlexey Lapshin           return Err;
182525d7b4fbSAlexey Lapshin       } else {
182625d7b4fbSAlexey Lapshin         Expected<typename ELFFile<ELFT>::Elf_Rela_Range> Relas =
182725d7b4fbSAlexey Lapshin             ElfFile.relas(*Shdr);
182825d7b4fbSAlexey Lapshin         if (!Relas)
182925d7b4fbSAlexey Lapshin           return Relas.takeError();
183025d7b4fbSAlexey Lapshin 
183125d7b4fbSAlexey Lapshin         if (Error Err = initRelocations(RelSec, *Relas))
183225d7b4fbSAlexey Lapshin           return Err;
183325d7b4fbSAlexey Lapshin       }
183425d7b4fbSAlexey Lapshin     } else if (auto GroupSec = dyn_cast<GroupSection>(&Sec)) {
183525d7b4fbSAlexey Lapshin       if (Error Err = initGroupSection(GroupSec))
183625d7b4fbSAlexey Lapshin         return Err;
183725d7b4fbSAlexey Lapshin     }
183825d7b4fbSAlexey Lapshin   }
183925d7b4fbSAlexey Lapshin 
184025d7b4fbSAlexey Lapshin   return Error::success();
184125d7b4fbSAlexey Lapshin }
184225d7b4fbSAlexey Lapshin 
build(bool EnsureSymtab)184325d7b4fbSAlexey Lapshin template <class ELFT> Error ELFBuilder<ELFT>::build(bool EnsureSymtab) {
184425d7b4fbSAlexey Lapshin   if (Error E = readSectionHeaders())
184525d7b4fbSAlexey Lapshin     return E;
184625d7b4fbSAlexey Lapshin   if (Error E = findEhdrOffset())
184725d7b4fbSAlexey Lapshin     return E;
184825d7b4fbSAlexey Lapshin 
184925d7b4fbSAlexey Lapshin   // The ELFFile whose ELF headers and program headers are copied into the
185025d7b4fbSAlexey Lapshin   // output file. Normally the same as ElfFile, but if we're extracting a
185125d7b4fbSAlexey Lapshin   // loadable partition it will point to the partition's headers.
185225d7b4fbSAlexey Lapshin   Expected<ELFFile<ELFT>> HeadersFile = ELFFile<ELFT>::create(toStringRef(
185325d7b4fbSAlexey Lapshin       {ElfFile.base() + EhdrOffset, ElfFile.getBufSize() - EhdrOffset}));
185425d7b4fbSAlexey Lapshin   if (!HeadersFile)
185525d7b4fbSAlexey Lapshin     return HeadersFile.takeError();
185625d7b4fbSAlexey Lapshin 
185725d7b4fbSAlexey Lapshin   const typename ELFFile<ELFT>::Elf_Ehdr &Ehdr = HeadersFile->getHeader();
185825d7b4fbSAlexey Lapshin   Obj.OSABI = Ehdr.e_ident[EI_OSABI];
185925d7b4fbSAlexey Lapshin   Obj.ABIVersion = Ehdr.e_ident[EI_ABIVERSION];
186025d7b4fbSAlexey Lapshin   Obj.Type = Ehdr.e_type;
186125d7b4fbSAlexey Lapshin   Obj.Machine = Ehdr.e_machine;
186225d7b4fbSAlexey Lapshin   Obj.Version = Ehdr.e_version;
186325d7b4fbSAlexey Lapshin   Obj.Entry = Ehdr.e_entry;
186425d7b4fbSAlexey Lapshin   Obj.Flags = Ehdr.e_flags;
186525d7b4fbSAlexey Lapshin 
186625d7b4fbSAlexey Lapshin   if (Error E = readSections(EnsureSymtab))
186725d7b4fbSAlexey Lapshin     return E;
186825d7b4fbSAlexey Lapshin   return readProgramHeaders(*HeadersFile);
186925d7b4fbSAlexey Lapshin }
187025d7b4fbSAlexey Lapshin 
1871c008e92bSKazu Hirata Writer::~Writer() = default;
187225d7b4fbSAlexey Lapshin 
1873c008e92bSKazu Hirata Reader::~Reader() = default;
187425d7b4fbSAlexey Lapshin 
187525d7b4fbSAlexey Lapshin Expected<std::unique_ptr<Object>>
create(bool) const187625d7b4fbSAlexey Lapshin BinaryReader::create(bool /*EnsureSymtab*/) const {
187725d7b4fbSAlexey Lapshin   return BinaryELFBuilder(MemBuf, NewSymbolVisibility).build();
187825d7b4fbSAlexey Lapshin }
187925d7b4fbSAlexey Lapshin 
parse() const188025d7b4fbSAlexey Lapshin Expected<std::vector<IHexRecord>> IHexReader::parse() const {
188125d7b4fbSAlexey Lapshin   SmallVector<StringRef, 16> Lines;
188225d7b4fbSAlexey Lapshin   std::vector<IHexRecord> Records;
188325d7b4fbSAlexey Lapshin   bool HasSections = false;
188425d7b4fbSAlexey Lapshin 
188525d7b4fbSAlexey Lapshin   MemBuf->getBuffer().split(Lines, '\n');
188625d7b4fbSAlexey Lapshin   Records.reserve(Lines.size());
188725d7b4fbSAlexey Lapshin   for (size_t LineNo = 1; LineNo <= Lines.size(); ++LineNo) {
188825d7b4fbSAlexey Lapshin     StringRef Line = Lines[LineNo - 1].trim();
188925d7b4fbSAlexey Lapshin     if (Line.empty())
189025d7b4fbSAlexey Lapshin       continue;
189125d7b4fbSAlexey Lapshin 
189225d7b4fbSAlexey Lapshin     Expected<IHexRecord> R = IHexRecord::parse(Line);
189325d7b4fbSAlexey Lapshin     if (!R)
189425d7b4fbSAlexey Lapshin       return parseError(LineNo, R.takeError());
189525d7b4fbSAlexey Lapshin     if (R->Type == IHexRecord::EndOfFile)
189625d7b4fbSAlexey Lapshin       break;
189725d7b4fbSAlexey Lapshin     HasSections |= (R->Type == IHexRecord::Data);
189825d7b4fbSAlexey Lapshin     Records.push_back(*R);
189925d7b4fbSAlexey Lapshin   }
190025d7b4fbSAlexey Lapshin   if (!HasSections)
190125d7b4fbSAlexey Lapshin     return parseError(-1U, "no sections");
190225d7b4fbSAlexey Lapshin 
190325d7b4fbSAlexey Lapshin   return std::move(Records);
190425d7b4fbSAlexey Lapshin }
190525d7b4fbSAlexey Lapshin 
190625d7b4fbSAlexey Lapshin Expected<std::unique_ptr<Object>>
create(bool) const190725d7b4fbSAlexey Lapshin IHexReader::create(bool /*EnsureSymtab*/) const {
190825d7b4fbSAlexey Lapshin   Expected<std::vector<IHexRecord>> Records = parse();
190925d7b4fbSAlexey Lapshin   if (!Records)
191025d7b4fbSAlexey Lapshin     return Records.takeError();
191125d7b4fbSAlexey Lapshin 
191225d7b4fbSAlexey Lapshin   return IHexELFBuilder(*Records).build();
191325d7b4fbSAlexey Lapshin }
191425d7b4fbSAlexey Lapshin 
create(bool EnsureSymtab) const191525d7b4fbSAlexey Lapshin Expected<std::unique_ptr<Object>> ELFReader::create(bool EnsureSymtab) const {
191625d7b4fbSAlexey Lapshin   auto Obj = std::make_unique<Object>();
191725d7b4fbSAlexey Lapshin   if (auto *O = dyn_cast<ELFObjectFile<ELF32LE>>(Bin)) {
191825d7b4fbSAlexey Lapshin     ELFBuilder<ELF32LE> Builder(*O, *Obj, ExtractPartition);
191925d7b4fbSAlexey Lapshin     if (Error Err = Builder.build(EnsureSymtab))
192025d7b4fbSAlexey Lapshin       return std::move(Err);
192125d7b4fbSAlexey Lapshin     return std::move(Obj);
192225d7b4fbSAlexey Lapshin   } else if (auto *O = dyn_cast<ELFObjectFile<ELF64LE>>(Bin)) {
192325d7b4fbSAlexey Lapshin     ELFBuilder<ELF64LE> Builder(*O, *Obj, ExtractPartition);
192425d7b4fbSAlexey Lapshin     if (Error Err = Builder.build(EnsureSymtab))
192525d7b4fbSAlexey Lapshin       return std::move(Err);
192625d7b4fbSAlexey Lapshin     return std::move(Obj);
192725d7b4fbSAlexey Lapshin   } else if (auto *O = dyn_cast<ELFObjectFile<ELF32BE>>(Bin)) {
192825d7b4fbSAlexey Lapshin     ELFBuilder<ELF32BE> Builder(*O, *Obj, ExtractPartition);
192925d7b4fbSAlexey Lapshin     if (Error Err = Builder.build(EnsureSymtab))
193025d7b4fbSAlexey Lapshin       return std::move(Err);
193125d7b4fbSAlexey Lapshin     return std::move(Obj);
193225d7b4fbSAlexey Lapshin   } else if (auto *O = dyn_cast<ELFObjectFile<ELF64BE>>(Bin)) {
193325d7b4fbSAlexey Lapshin     ELFBuilder<ELF64BE> Builder(*O, *Obj, ExtractPartition);
193425d7b4fbSAlexey Lapshin     if (Error Err = Builder.build(EnsureSymtab))
193525d7b4fbSAlexey Lapshin       return std::move(Err);
193625d7b4fbSAlexey Lapshin     return std::move(Obj);
193725d7b4fbSAlexey Lapshin   }
193825d7b4fbSAlexey Lapshin   return createStringError(errc::invalid_argument, "invalid file type");
193925d7b4fbSAlexey Lapshin }
194025d7b4fbSAlexey Lapshin 
writeEhdr()194125d7b4fbSAlexey Lapshin template <class ELFT> void ELFWriter<ELFT>::writeEhdr() {
194225d7b4fbSAlexey Lapshin   Elf_Ehdr &Ehdr = *reinterpret_cast<Elf_Ehdr *>(Buf->getBufferStart());
194325d7b4fbSAlexey Lapshin   std::fill(Ehdr.e_ident, Ehdr.e_ident + 16, 0);
194425d7b4fbSAlexey Lapshin   Ehdr.e_ident[EI_MAG0] = 0x7f;
194525d7b4fbSAlexey Lapshin   Ehdr.e_ident[EI_MAG1] = 'E';
194625d7b4fbSAlexey Lapshin   Ehdr.e_ident[EI_MAG2] = 'L';
194725d7b4fbSAlexey Lapshin   Ehdr.e_ident[EI_MAG3] = 'F';
194825d7b4fbSAlexey Lapshin   Ehdr.e_ident[EI_CLASS] = ELFT::Is64Bits ? ELFCLASS64 : ELFCLASS32;
194925d7b4fbSAlexey Lapshin   Ehdr.e_ident[EI_DATA] =
195025d7b4fbSAlexey Lapshin       ELFT::TargetEndianness == support::big ? ELFDATA2MSB : ELFDATA2LSB;
195125d7b4fbSAlexey Lapshin   Ehdr.e_ident[EI_VERSION] = EV_CURRENT;
195225d7b4fbSAlexey Lapshin   Ehdr.e_ident[EI_OSABI] = Obj.OSABI;
195325d7b4fbSAlexey Lapshin   Ehdr.e_ident[EI_ABIVERSION] = Obj.ABIVersion;
195425d7b4fbSAlexey Lapshin 
195525d7b4fbSAlexey Lapshin   Ehdr.e_type = Obj.Type;
195625d7b4fbSAlexey Lapshin   Ehdr.e_machine = Obj.Machine;
195725d7b4fbSAlexey Lapshin   Ehdr.e_version = Obj.Version;
195825d7b4fbSAlexey Lapshin   Ehdr.e_entry = Obj.Entry;
195925d7b4fbSAlexey Lapshin   // We have to use the fully-qualified name llvm::size
196025d7b4fbSAlexey Lapshin   // since some compilers complain on ambiguous resolution.
196125d7b4fbSAlexey Lapshin   Ehdr.e_phnum = llvm::size(Obj.segments());
196225d7b4fbSAlexey Lapshin   Ehdr.e_phoff = (Ehdr.e_phnum != 0) ? Obj.ProgramHdrSegment.Offset : 0;
196325d7b4fbSAlexey Lapshin   Ehdr.e_phentsize = (Ehdr.e_phnum != 0) ? sizeof(Elf_Phdr) : 0;
196425d7b4fbSAlexey Lapshin   Ehdr.e_flags = Obj.Flags;
196525d7b4fbSAlexey Lapshin   Ehdr.e_ehsize = sizeof(Elf_Ehdr);
196625d7b4fbSAlexey Lapshin   if (WriteSectionHeaders && Obj.sections().size() != 0) {
196725d7b4fbSAlexey Lapshin     Ehdr.e_shentsize = sizeof(Elf_Shdr);
196825d7b4fbSAlexey Lapshin     Ehdr.e_shoff = Obj.SHOff;
196925d7b4fbSAlexey Lapshin     // """
197025d7b4fbSAlexey Lapshin     // If the number of sections is greater than or equal to
197125d7b4fbSAlexey Lapshin     // SHN_LORESERVE (0xff00), this member has the value zero and the actual
197225d7b4fbSAlexey Lapshin     // number of section header table entries is contained in the sh_size field
197325d7b4fbSAlexey Lapshin     // of the section header at index 0.
197425d7b4fbSAlexey Lapshin     // """
197525d7b4fbSAlexey Lapshin     auto Shnum = Obj.sections().size() + 1;
197625d7b4fbSAlexey Lapshin     if (Shnum >= SHN_LORESERVE)
197725d7b4fbSAlexey Lapshin       Ehdr.e_shnum = 0;
197825d7b4fbSAlexey Lapshin     else
197925d7b4fbSAlexey Lapshin       Ehdr.e_shnum = Shnum;
198025d7b4fbSAlexey Lapshin     // """
198125d7b4fbSAlexey Lapshin     // If the section name string table section index is greater than or equal
198225d7b4fbSAlexey Lapshin     // to SHN_LORESERVE (0xff00), this member has the value SHN_XINDEX (0xffff)
198325d7b4fbSAlexey Lapshin     // and the actual index of the section name string table section is
198425d7b4fbSAlexey Lapshin     // contained in the sh_link field of the section header at index 0.
198525d7b4fbSAlexey Lapshin     // """
198625d7b4fbSAlexey Lapshin     if (Obj.SectionNames->Index >= SHN_LORESERVE)
198725d7b4fbSAlexey Lapshin       Ehdr.e_shstrndx = SHN_XINDEX;
198825d7b4fbSAlexey Lapshin     else
198925d7b4fbSAlexey Lapshin       Ehdr.e_shstrndx = Obj.SectionNames->Index;
199025d7b4fbSAlexey Lapshin   } else {
199125d7b4fbSAlexey Lapshin     Ehdr.e_shentsize = 0;
199225d7b4fbSAlexey Lapshin     Ehdr.e_shoff = 0;
199325d7b4fbSAlexey Lapshin     Ehdr.e_shnum = 0;
199425d7b4fbSAlexey Lapshin     Ehdr.e_shstrndx = 0;
199525d7b4fbSAlexey Lapshin   }
199625d7b4fbSAlexey Lapshin }
199725d7b4fbSAlexey Lapshin 
writePhdrs()199825d7b4fbSAlexey Lapshin template <class ELFT> void ELFWriter<ELFT>::writePhdrs() {
199925d7b4fbSAlexey Lapshin   for (auto &Seg : Obj.segments())
200025d7b4fbSAlexey Lapshin     writePhdr(Seg);
200125d7b4fbSAlexey Lapshin }
200225d7b4fbSAlexey Lapshin 
writeShdrs()200325d7b4fbSAlexey Lapshin template <class ELFT> void ELFWriter<ELFT>::writeShdrs() {
200425d7b4fbSAlexey Lapshin   // This reference serves to write the dummy section header at the begining
200525d7b4fbSAlexey Lapshin   // of the file. It is not used for anything else
200625d7b4fbSAlexey Lapshin   Elf_Shdr &Shdr =
200725d7b4fbSAlexey Lapshin       *reinterpret_cast<Elf_Shdr *>(Buf->getBufferStart() + Obj.SHOff);
200825d7b4fbSAlexey Lapshin   Shdr.sh_name = 0;
200925d7b4fbSAlexey Lapshin   Shdr.sh_type = SHT_NULL;
201025d7b4fbSAlexey Lapshin   Shdr.sh_flags = 0;
201125d7b4fbSAlexey Lapshin   Shdr.sh_addr = 0;
201225d7b4fbSAlexey Lapshin   Shdr.sh_offset = 0;
201325d7b4fbSAlexey Lapshin   // See writeEhdr for why we do this.
201425d7b4fbSAlexey Lapshin   uint64_t Shnum = Obj.sections().size() + 1;
201525d7b4fbSAlexey Lapshin   if (Shnum >= SHN_LORESERVE)
201625d7b4fbSAlexey Lapshin     Shdr.sh_size = Shnum;
201725d7b4fbSAlexey Lapshin   else
201825d7b4fbSAlexey Lapshin     Shdr.sh_size = 0;
201925d7b4fbSAlexey Lapshin   // See writeEhdr for why we do this.
202025d7b4fbSAlexey Lapshin   if (Obj.SectionNames != nullptr && Obj.SectionNames->Index >= SHN_LORESERVE)
202125d7b4fbSAlexey Lapshin     Shdr.sh_link = Obj.SectionNames->Index;
202225d7b4fbSAlexey Lapshin   else
202325d7b4fbSAlexey Lapshin     Shdr.sh_link = 0;
202425d7b4fbSAlexey Lapshin   Shdr.sh_info = 0;
202525d7b4fbSAlexey Lapshin   Shdr.sh_addralign = 0;
202625d7b4fbSAlexey Lapshin   Shdr.sh_entsize = 0;
202725d7b4fbSAlexey Lapshin 
202825d7b4fbSAlexey Lapshin   for (SectionBase &Sec : Obj.sections())
202925d7b4fbSAlexey Lapshin     writeShdr(Sec);
203025d7b4fbSAlexey Lapshin }
203125d7b4fbSAlexey Lapshin 
writeSectionData()203225d7b4fbSAlexey Lapshin template <class ELFT> Error ELFWriter<ELFT>::writeSectionData() {
203325d7b4fbSAlexey Lapshin   for (SectionBase &Sec : Obj.sections())
203425d7b4fbSAlexey Lapshin     // Segments are responsible for writing their contents, so only write the
203525d7b4fbSAlexey Lapshin     // section data if the section is not in a segment. Note that this renders
203625d7b4fbSAlexey Lapshin     // sections in segments effectively immutable.
203725d7b4fbSAlexey Lapshin     if (Sec.ParentSegment == nullptr)
203825d7b4fbSAlexey Lapshin       if (Error Err = Sec.accept(*SecWriter))
203925d7b4fbSAlexey Lapshin         return Err;
204025d7b4fbSAlexey Lapshin 
204125d7b4fbSAlexey Lapshin   return Error::success();
204225d7b4fbSAlexey Lapshin }
204325d7b4fbSAlexey Lapshin 
writeSegmentData()204425d7b4fbSAlexey Lapshin template <class ELFT> void ELFWriter<ELFT>::writeSegmentData() {
204525d7b4fbSAlexey Lapshin   for (Segment &Seg : Obj.segments()) {
204625d7b4fbSAlexey Lapshin     size_t Size = std::min<size_t>(Seg.FileSize, Seg.getContents().size());
204725d7b4fbSAlexey Lapshin     std::memcpy(Buf->getBufferStart() + Seg.Offset, Seg.getContents().data(),
204825d7b4fbSAlexey Lapshin                 Size);
204925d7b4fbSAlexey Lapshin   }
205025d7b4fbSAlexey Lapshin 
205125d7b4fbSAlexey Lapshin   for (auto it : Obj.getUpdatedSections()) {
205225d7b4fbSAlexey Lapshin     SectionBase *Sec = it.first;
205325d7b4fbSAlexey Lapshin     ArrayRef<uint8_t> Data = it.second;
205425d7b4fbSAlexey Lapshin 
205525d7b4fbSAlexey Lapshin     auto *Parent = Sec->ParentSegment;
205625d7b4fbSAlexey Lapshin     assert(Parent && "This section should've been part of a segment.");
205725d7b4fbSAlexey Lapshin     uint64_t Offset =
205825d7b4fbSAlexey Lapshin         Sec->OriginalOffset - Parent->OriginalOffset + Parent->Offset;
205925d7b4fbSAlexey Lapshin     llvm::copy(Data, Buf->getBufferStart() + Offset);
206025d7b4fbSAlexey Lapshin   }
206125d7b4fbSAlexey Lapshin 
206225d7b4fbSAlexey Lapshin   // Iterate over removed sections and overwrite their old data with zeroes.
206325d7b4fbSAlexey Lapshin   for (auto &Sec : Obj.removedSections()) {
206425d7b4fbSAlexey Lapshin     Segment *Parent = Sec.ParentSegment;
206525d7b4fbSAlexey Lapshin     if (Parent == nullptr || Sec.Type == SHT_NOBITS || Sec.Size == 0)
206625d7b4fbSAlexey Lapshin       continue;
206725d7b4fbSAlexey Lapshin     uint64_t Offset =
206825d7b4fbSAlexey Lapshin         Sec.OriginalOffset - Parent->OriginalOffset + Parent->Offset;
206925d7b4fbSAlexey Lapshin     std::memset(Buf->getBufferStart() + Offset, 0, Sec.Size);
207025d7b4fbSAlexey Lapshin   }
207125d7b4fbSAlexey Lapshin }
207225d7b4fbSAlexey Lapshin 
207325d7b4fbSAlexey Lapshin template <class ELFT>
ELFWriter(Object & Obj,raw_ostream & Buf,bool WSH,bool OnlyKeepDebug)207425d7b4fbSAlexey Lapshin ELFWriter<ELFT>::ELFWriter(Object &Obj, raw_ostream &Buf, bool WSH,
207525d7b4fbSAlexey Lapshin                            bool OnlyKeepDebug)
207625d7b4fbSAlexey Lapshin     : Writer(Obj, Buf), WriteSectionHeaders(WSH && Obj.HadShdrs),
207725d7b4fbSAlexey Lapshin       OnlyKeepDebug(OnlyKeepDebug) {}
207825d7b4fbSAlexey Lapshin 
updateSection(StringRef Name,ArrayRef<uint8_t> Data)207925d7b4fbSAlexey Lapshin Error Object::updateSection(StringRef Name, ArrayRef<uint8_t> Data) {
208025d7b4fbSAlexey Lapshin   auto It = llvm::find_if(Sections,
208125d7b4fbSAlexey Lapshin                           [&](const SecPtr &Sec) { return Sec->Name == Name; });
208225d7b4fbSAlexey Lapshin   if (It == Sections.end())
208325d7b4fbSAlexey Lapshin     return createStringError(errc::invalid_argument, "section '%s' not found",
208425d7b4fbSAlexey Lapshin                              Name.str().c_str());
208525d7b4fbSAlexey Lapshin 
208625d7b4fbSAlexey Lapshin   auto *OldSec = It->get();
208725d7b4fbSAlexey Lapshin   if (!OldSec->hasContents())
208825d7b4fbSAlexey Lapshin     return createStringError(
208925d7b4fbSAlexey Lapshin         errc::invalid_argument,
209025d7b4fbSAlexey Lapshin         "section '%s' cannot be updated because it does not have contents",
209125d7b4fbSAlexey Lapshin         Name.str().c_str());
209225d7b4fbSAlexey Lapshin 
209325d7b4fbSAlexey Lapshin   if (Data.size() > OldSec->Size && OldSec->ParentSegment)
209425d7b4fbSAlexey Lapshin     return createStringError(errc::invalid_argument,
209525d7b4fbSAlexey Lapshin                              "cannot fit data of size %zu into section '%s' "
209625d7b4fbSAlexey Lapshin                              "with size %zu that is part of a segment",
209725d7b4fbSAlexey Lapshin                              Data.size(), Name.str().c_str(), OldSec->Size);
209825d7b4fbSAlexey Lapshin 
209925d7b4fbSAlexey Lapshin   if (!OldSec->ParentSegment) {
210025d7b4fbSAlexey Lapshin     *It = std::make_unique<OwnedDataSection>(*OldSec, Data);
210125d7b4fbSAlexey Lapshin   } else {
210225d7b4fbSAlexey Lapshin     // The segment writer will be in charge of updating these contents.
210325d7b4fbSAlexey Lapshin     OldSec->Size = Data.size();
210425d7b4fbSAlexey Lapshin     UpdatedSections[OldSec] = Data;
210525d7b4fbSAlexey Lapshin   }
210625d7b4fbSAlexey Lapshin 
210725d7b4fbSAlexey Lapshin   return Error::success();
210825d7b4fbSAlexey Lapshin }
210925d7b4fbSAlexey Lapshin 
removeSections(bool AllowBrokenLinks,std::function<bool (const SectionBase &)> ToRemove)211025d7b4fbSAlexey Lapshin Error Object::removeSections(
211125d7b4fbSAlexey Lapshin     bool AllowBrokenLinks, std::function<bool(const SectionBase &)> ToRemove) {
211225d7b4fbSAlexey Lapshin 
211325d7b4fbSAlexey Lapshin   auto Iter = std::stable_partition(
211425d7b4fbSAlexey Lapshin       std::begin(Sections), std::end(Sections), [=](const SecPtr &Sec) {
211525d7b4fbSAlexey Lapshin         if (ToRemove(*Sec))
211625d7b4fbSAlexey Lapshin           return false;
211725d7b4fbSAlexey Lapshin         if (auto RelSec = dyn_cast<RelocationSectionBase>(Sec.get())) {
211825d7b4fbSAlexey Lapshin           if (auto ToRelSec = RelSec->getSection())
211925d7b4fbSAlexey Lapshin             return !ToRemove(*ToRelSec);
212025d7b4fbSAlexey Lapshin         }
212125d7b4fbSAlexey Lapshin         return true;
212225d7b4fbSAlexey Lapshin       });
212325d7b4fbSAlexey Lapshin   if (SymbolTable != nullptr && ToRemove(*SymbolTable))
212425d7b4fbSAlexey Lapshin     SymbolTable = nullptr;
212525d7b4fbSAlexey Lapshin   if (SectionNames != nullptr && ToRemove(*SectionNames))
212625d7b4fbSAlexey Lapshin     SectionNames = nullptr;
212725d7b4fbSAlexey Lapshin   if (SectionIndexTable != nullptr && ToRemove(*SectionIndexTable))
212825d7b4fbSAlexey Lapshin     SectionIndexTable = nullptr;
212925d7b4fbSAlexey Lapshin   // Now make sure there are no remaining references to the sections that will
213025d7b4fbSAlexey Lapshin   // be removed. Sometimes it is impossible to remove a reference so we emit
213125d7b4fbSAlexey Lapshin   // an error here instead.
213225d7b4fbSAlexey Lapshin   std::unordered_set<const SectionBase *> RemoveSections;
213325d7b4fbSAlexey Lapshin   RemoveSections.reserve(std::distance(Iter, std::end(Sections)));
213425d7b4fbSAlexey Lapshin   for (auto &RemoveSec : make_range(Iter, std::end(Sections))) {
213525d7b4fbSAlexey Lapshin     for (auto &Segment : Segments)
213625d7b4fbSAlexey Lapshin       Segment->removeSection(RemoveSec.get());
213725d7b4fbSAlexey Lapshin     RemoveSec->onRemove();
213825d7b4fbSAlexey Lapshin     RemoveSections.insert(RemoveSec.get());
213925d7b4fbSAlexey Lapshin   }
214025d7b4fbSAlexey Lapshin 
214125d7b4fbSAlexey Lapshin   // For each section that remains alive, we want to remove the dead references.
214225d7b4fbSAlexey Lapshin   // This either might update the content of the section (e.g. remove symbols
214325d7b4fbSAlexey Lapshin   // from symbol table that belongs to removed section) or trigger an error if
214425d7b4fbSAlexey Lapshin   // a live section critically depends on a section being removed somehow
214525d7b4fbSAlexey Lapshin   // (e.g. the removed section is referenced by a relocation).
214625d7b4fbSAlexey Lapshin   for (auto &KeepSec : make_range(std::begin(Sections), Iter)) {
214725d7b4fbSAlexey Lapshin     if (Error E = KeepSec->removeSectionReferences(
214825d7b4fbSAlexey Lapshin             AllowBrokenLinks, [&RemoveSections](const SectionBase *Sec) {
214925d7b4fbSAlexey Lapshin               return RemoveSections.find(Sec) != RemoveSections.end();
215025d7b4fbSAlexey Lapshin             }))
215125d7b4fbSAlexey Lapshin       return E;
215225d7b4fbSAlexey Lapshin   }
215325d7b4fbSAlexey Lapshin 
215425d7b4fbSAlexey Lapshin   // Transfer removed sections into the Object RemovedSections container for use
215525d7b4fbSAlexey Lapshin   // later.
215625d7b4fbSAlexey Lapshin   std::move(Iter, Sections.end(), std::back_inserter(RemovedSections));
215725d7b4fbSAlexey Lapshin   // Now finally get rid of them all together.
215825d7b4fbSAlexey Lapshin   Sections.erase(Iter, std::end(Sections));
215925d7b4fbSAlexey Lapshin   return Error::success();
216025d7b4fbSAlexey Lapshin }
216125d7b4fbSAlexey Lapshin 
replaceSections(const DenseMap<SectionBase *,SectionBase * > & FromTo)216225d7b4fbSAlexey Lapshin Error Object::replaceSections(
216325d7b4fbSAlexey Lapshin     const DenseMap<SectionBase *, SectionBase *> &FromTo) {
216425d7b4fbSAlexey Lapshin   auto SectionIndexLess = [](const SecPtr &Lhs, const SecPtr &Rhs) {
216525d7b4fbSAlexey Lapshin     return Lhs->Index < Rhs->Index;
216625d7b4fbSAlexey Lapshin   };
216725d7b4fbSAlexey Lapshin   assert(llvm::is_sorted(Sections, SectionIndexLess) &&
216825d7b4fbSAlexey Lapshin          "Sections are expected to be sorted by Index");
216925d7b4fbSAlexey Lapshin   // Set indices of new sections so that they can be later sorted into positions
217025d7b4fbSAlexey Lapshin   // of removed ones.
217125d7b4fbSAlexey Lapshin   for (auto &I : FromTo)
217225d7b4fbSAlexey Lapshin     I.second->Index = I.first->Index;
217325d7b4fbSAlexey Lapshin 
217425d7b4fbSAlexey Lapshin   // Notify all sections about the replacement.
217525d7b4fbSAlexey Lapshin   for (auto &Sec : Sections)
217625d7b4fbSAlexey Lapshin     Sec->replaceSectionReferences(FromTo);
217725d7b4fbSAlexey Lapshin 
217825d7b4fbSAlexey Lapshin   if (Error E = removeSections(
217925d7b4fbSAlexey Lapshin           /*AllowBrokenLinks=*/false,
218025d7b4fbSAlexey Lapshin           [=](const SectionBase &Sec) { return FromTo.count(&Sec) > 0; }))
218125d7b4fbSAlexey Lapshin     return E;
218225d7b4fbSAlexey Lapshin   llvm::sort(Sections, SectionIndexLess);
218325d7b4fbSAlexey Lapshin   return Error::success();
218425d7b4fbSAlexey Lapshin }
218525d7b4fbSAlexey Lapshin 
removeSymbols(function_ref<bool (const Symbol &)> ToRemove)218625d7b4fbSAlexey Lapshin Error Object::removeSymbols(function_ref<bool(const Symbol &)> ToRemove) {
218725d7b4fbSAlexey Lapshin   if (SymbolTable)
218825d7b4fbSAlexey Lapshin     for (const SecPtr &Sec : Sections)
218925d7b4fbSAlexey Lapshin       if (Error E = Sec->removeSymbols(ToRemove))
219025d7b4fbSAlexey Lapshin         return E;
219125d7b4fbSAlexey Lapshin   return Error::success();
219225d7b4fbSAlexey Lapshin }
219325d7b4fbSAlexey Lapshin 
addNewSymbolTable()219425d7b4fbSAlexey Lapshin Error Object::addNewSymbolTable() {
219525d7b4fbSAlexey Lapshin   assert(!SymbolTable && "Object must not has a SymbolTable.");
219625d7b4fbSAlexey Lapshin 
219725d7b4fbSAlexey Lapshin   // Reuse an existing SHT_STRTAB section if it exists.
219825d7b4fbSAlexey Lapshin   StringTableSection *StrTab = nullptr;
219925d7b4fbSAlexey Lapshin   for (SectionBase &Sec : sections()) {
220025d7b4fbSAlexey Lapshin     if (Sec.Type == ELF::SHT_STRTAB && !(Sec.Flags & SHF_ALLOC)) {
220125d7b4fbSAlexey Lapshin       StrTab = static_cast<StringTableSection *>(&Sec);
220225d7b4fbSAlexey Lapshin 
220325d7b4fbSAlexey Lapshin       // Prefer a string table that is not the section header string table, if
220425d7b4fbSAlexey Lapshin       // such a table exists.
220525d7b4fbSAlexey Lapshin       if (SectionNames != &Sec)
220625d7b4fbSAlexey Lapshin         break;
220725d7b4fbSAlexey Lapshin     }
220825d7b4fbSAlexey Lapshin   }
220925d7b4fbSAlexey Lapshin   if (!StrTab)
221025d7b4fbSAlexey Lapshin     StrTab = &addSection<StringTableSection>();
221125d7b4fbSAlexey Lapshin 
221225d7b4fbSAlexey Lapshin   SymbolTableSection &SymTab = addSection<SymbolTableSection>();
221325d7b4fbSAlexey Lapshin   SymTab.Name = ".symtab";
221425d7b4fbSAlexey Lapshin   SymTab.Link = StrTab->Index;
221525d7b4fbSAlexey Lapshin   if (Error Err = SymTab.initialize(sections()))
221625d7b4fbSAlexey Lapshin     return Err;
221725d7b4fbSAlexey Lapshin   SymTab.addSymbol("", 0, 0, nullptr, 0, 0, 0, 0);
221825d7b4fbSAlexey Lapshin 
221925d7b4fbSAlexey Lapshin   SymbolTable = &SymTab;
222025d7b4fbSAlexey Lapshin 
222125d7b4fbSAlexey Lapshin   return Error::success();
222225d7b4fbSAlexey Lapshin }
222325d7b4fbSAlexey Lapshin 
222425d7b4fbSAlexey Lapshin // Orders segments such that if x = y->ParentSegment then y comes before x.
orderSegments(std::vector<Segment * > & Segments)222525d7b4fbSAlexey Lapshin static void orderSegments(std::vector<Segment *> &Segments) {
222625d7b4fbSAlexey Lapshin   llvm::stable_sort(Segments, compareSegmentsByOffset);
222725d7b4fbSAlexey Lapshin }
222825d7b4fbSAlexey Lapshin 
222925d7b4fbSAlexey Lapshin // This function finds a consistent layout for a list of segments starting from
223025d7b4fbSAlexey Lapshin // an Offset. It assumes that Segments have been sorted by orderSegments and
223125d7b4fbSAlexey Lapshin // returns an Offset one past the end of the last segment.
layoutSegments(std::vector<Segment * > & Segments,uint64_t Offset)223225d7b4fbSAlexey Lapshin static uint64_t layoutSegments(std::vector<Segment *> &Segments,
223325d7b4fbSAlexey Lapshin                                uint64_t Offset) {
223425d7b4fbSAlexey Lapshin   assert(llvm::is_sorted(Segments, compareSegmentsByOffset));
223525d7b4fbSAlexey Lapshin   // The only way a segment should move is if a section was between two
223625d7b4fbSAlexey Lapshin   // segments and that section was removed. If that section isn't in a segment
223725d7b4fbSAlexey Lapshin   // then it's acceptable, but not ideal, to simply move it to after the
223825d7b4fbSAlexey Lapshin   // segments. So we can simply layout segments one after the other accounting
223925d7b4fbSAlexey Lapshin   // for alignment.
224025d7b4fbSAlexey Lapshin   for (Segment *Seg : Segments) {
224125d7b4fbSAlexey Lapshin     // We assume that segments have been ordered by OriginalOffset and Index
224225d7b4fbSAlexey Lapshin     // such that a parent segment will always come before a child segment in
224325d7b4fbSAlexey Lapshin     // OrderedSegments. This means that the Offset of the ParentSegment should
224425d7b4fbSAlexey Lapshin     // already be set and we can set our offset relative to it.
224525d7b4fbSAlexey Lapshin     if (Seg->ParentSegment != nullptr) {
224625d7b4fbSAlexey Lapshin       Segment *Parent = Seg->ParentSegment;
224725d7b4fbSAlexey Lapshin       Seg->Offset =
224825d7b4fbSAlexey Lapshin           Parent->Offset + Seg->OriginalOffset - Parent->OriginalOffset;
224925d7b4fbSAlexey Lapshin     } else {
225025d7b4fbSAlexey Lapshin       Seg->Offset =
225125d7b4fbSAlexey Lapshin           alignTo(Offset, std::max<uint64_t>(Seg->Align, 1), Seg->VAddr);
225225d7b4fbSAlexey Lapshin     }
225325d7b4fbSAlexey Lapshin     Offset = std::max(Offset, Seg->Offset + Seg->FileSize);
225425d7b4fbSAlexey Lapshin   }
225525d7b4fbSAlexey Lapshin   return Offset;
225625d7b4fbSAlexey Lapshin }
225725d7b4fbSAlexey Lapshin 
225825d7b4fbSAlexey Lapshin // This function finds a consistent layout for a list of sections. It assumes
225925d7b4fbSAlexey Lapshin // that the ->ParentSegment of each section has already been laid out. The
226025d7b4fbSAlexey Lapshin // supplied starting Offset is used for the starting offset of any section that
226125d7b4fbSAlexey Lapshin // does not have a ParentSegment. It returns either the offset given if all
226225d7b4fbSAlexey Lapshin // sections had a ParentSegment or an offset one past the last section if there
226325d7b4fbSAlexey Lapshin // was a section that didn't have a ParentSegment.
226425d7b4fbSAlexey Lapshin template <class Range>
layoutSections(Range Sections,uint64_t Offset)226525d7b4fbSAlexey Lapshin static uint64_t layoutSections(Range Sections, uint64_t Offset) {
226625d7b4fbSAlexey Lapshin   // Now the offset of every segment has been set we can assign the offsets
226725d7b4fbSAlexey Lapshin   // of each section. For sections that are covered by a segment we should use
226825d7b4fbSAlexey Lapshin   // the segment's original offset and the section's original offset to compute
226925d7b4fbSAlexey Lapshin   // the offset from the start of the segment. Using the offset from the start
227025d7b4fbSAlexey Lapshin   // of the segment we can assign a new offset to the section. For sections not
227125d7b4fbSAlexey Lapshin   // covered by segments we can just bump Offset to the next valid location.
227225d7b4fbSAlexey Lapshin   // While it is not necessary, layout the sections in the order based on their
227325d7b4fbSAlexey Lapshin   // original offsets to resemble the input file as close as possible.
227425d7b4fbSAlexey Lapshin   std::vector<SectionBase *> OutOfSegmentSections;
227525d7b4fbSAlexey Lapshin   uint32_t Index = 1;
227625d7b4fbSAlexey Lapshin   for (auto &Sec : Sections) {
227725d7b4fbSAlexey Lapshin     Sec.Index = Index++;
227825d7b4fbSAlexey Lapshin     if (Sec.ParentSegment != nullptr) {
227925d7b4fbSAlexey Lapshin       auto Segment = *Sec.ParentSegment;
228025d7b4fbSAlexey Lapshin       Sec.Offset =
228125d7b4fbSAlexey Lapshin           Segment.Offset + (Sec.OriginalOffset - Segment.OriginalOffset);
228225d7b4fbSAlexey Lapshin     } else
228325d7b4fbSAlexey Lapshin       OutOfSegmentSections.push_back(&Sec);
228425d7b4fbSAlexey Lapshin   }
228525d7b4fbSAlexey Lapshin 
228625d7b4fbSAlexey Lapshin   llvm::stable_sort(OutOfSegmentSections,
228725d7b4fbSAlexey Lapshin                     [](const SectionBase *Lhs, const SectionBase *Rhs) {
228825d7b4fbSAlexey Lapshin                       return Lhs->OriginalOffset < Rhs->OriginalOffset;
228925d7b4fbSAlexey Lapshin                     });
229025d7b4fbSAlexey Lapshin   for (auto *Sec : OutOfSegmentSections) {
229125d7b4fbSAlexey Lapshin     Offset = alignTo(Offset, Sec->Align == 0 ? 1 : Sec->Align);
229225d7b4fbSAlexey Lapshin     Sec->Offset = Offset;
229325d7b4fbSAlexey Lapshin     if (Sec->Type != SHT_NOBITS)
229425d7b4fbSAlexey Lapshin       Offset += Sec->Size;
229525d7b4fbSAlexey Lapshin   }
229625d7b4fbSAlexey Lapshin   return Offset;
229725d7b4fbSAlexey Lapshin }
229825d7b4fbSAlexey Lapshin 
229925d7b4fbSAlexey Lapshin // Rewrite sh_offset after some sections are changed to SHT_NOBITS and thus
230025d7b4fbSAlexey Lapshin // occupy no space in the file.
layoutSectionsForOnlyKeepDebug(Object & Obj,uint64_t Off)230125d7b4fbSAlexey Lapshin static uint64_t layoutSectionsForOnlyKeepDebug(Object &Obj, uint64_t Off) {
230225d7b4fbSAlexey Lapshin   // The layout algorithm requires the sections to be handled in the order of
230325d7b4fbSAlexey Lapshin   // their offsets in the input file, at least inside segments.
230425d7b4fbSAlexey Lapshin   std::vector<SectionBase *> Sections;
230525d7b4fbSAlexey Lapshin   Sections.reserve(Obj.sections().size());
230625d7b4fbSAlexey Lapshin   uint32_t Index = 1;
230725d7b4fbSAlexey Lapshin   for (auto &Sec : Obj.sections()) {
230825d7b4fbSAlexey Lapshin     Sec.Index = Index++;
230925d7b4fbSAlexey Lapshin     Sections.push_back(&Sec);
231025d7b4fbSAlexey Lapshin   }
231125d7b4fbSAlexey Lapshin   llvm::stable_sort(Sections,
231225d7b4fbSAlexey Lapshin                     [](const SectionBase *Lhs, const SectionBase *Rhs) {
231325d7b4fbSAlexey Lapshin                       return Lhs->OriginalOffset < Rhs->OriginalOffset;
231425d7b4fbSAlexey Lapshin                     });
231525d7b4fbSAlexey Lapshin 
231625d7b4fbSAlexey Lapshin   for (auto *Sec : Sections) {
231725d7b4fbSAlexey Lapshin     auto *FirstSec = Sec->ParentSegment && Sec->ParentSegment->Type == PT_LOAD
231825d7b4fbSAlexey Lapshin                          ? Sec->ParentSegment->firstSection()
231925d7b4fbSAlexey Lapshin                          : nullptr;
232025d7b4fbSAlexey Lapshin 
232125d7b4fbSAlexey Lapshin     // The first section in a PT_LOAD has to have congruent offset and address
232225d7b4fbSAlexey Lapshin     // modulo the alignment, which usually equals the maximum page size.
232325d7b4fbSAlexey Lapshin     if (FirstSec && FirstSec == Sec)
232425d7b4fbSAlexey Lapshin       Off = alignTo(Off, Sec->ParentSegment->Align, Sec->Addr);
232525d7b4fbSAlexey Lapshin 
232625d7b4fbSAlexey Lapshin     // sh_offset is not significant for SHT_NOBITS sections, but the congruence
232725d7b4fbSAlexey Lapshin     // rule must be followed if it is the first section in a PT_LOAD. Do not
232825d7b4fbSAlexey Lapshin     // advance Off.
232925d7b4fbSAlexey Lapshin     if (Sec->Type == SHT_NOBITS) {
233025d7b4fbSAlexey Lapshin       Sec->Offset = Off;
233125d7b4fbSAlexey Lapshin       continue;
233225d7b4fbSAlexey Lapshin     }
233325d7b4fbSAlexey Lapshin 
233425d7b4fbSAlexey Lapshin     if (!FirstSec) {
233525d7b4fbSAlexey Lapshin       // FirstSec being nullptr generally means that Sec does not have the
233625d7b4fbSAlexey Lapshin       // SHF_ALLOC flag.
233725d7b4fbSAlexey Lapshin       Off = Sec->Align ? alignTo(Off, Sec->Align) : Off;
233825d7b4fbSAlexey Lapshin     } else if (FirstSec != Sec) {
233925d7b4fbSAlexey Lapshin       // The offset is relative to the first section in the PT_LOAD segment. Use
234025d7b4fbSAlexey Lapshin       // sh_offset for non-SHF_ALLOC sections.
234125d7b4fbSAlexey Lapshin       Off = Sec->OriginalOffset - FirstSec->OriginalOffset + FirstSec->Offset;
234225d7b4fbSAlexey Lapshin     }
234325d7b4fbSAlexey Lapshin     Sec->Offset = Off;
234425d7b4fbSAlexey Lapshin     Off += Sec->Size;
234525d7b4fbSAlexey Lapshin   }
234625d7b4fbSAlexey Lapshin   return Off;
234725d7b4fbSAlexey Lapshin }
234825d7b4fbSAlexey Lapshin 
234925d7b4fbSAlexey Lapshin // Rewrite p_offset and p_filesz of non-PT_PHDR segments after sh_offset values
235025d7b4fbSAlexey Lapshin // have been updated.
layoutSegmentsForOnlyKeepDebug(std::vector<Segment * > & Segments,uint64_t HdrEnd)235125d7b4fbSAlexey Lapshin static uint64_t layoutSegmentsForOnlyKeepDebug(std::vector<Segment *> &Segments,
235225d7b4fbSAlexey Lapshin                                                uint64_t HdrEnd) {
235325d7b4fbSAlexey Lapshin   uint64_t MaxOffset = 0;
235425d7b4fbSAlexey Lapshin   for (Segment *Seg : Segments) {
235525d7b4fbSAlexey Lapshin     if (Seg->Type == PT_PHDR)
235625d7b4fbSAlexey Lapshin       continue;
235725d7b4fbSAlexey Lapshin 
235825d7b4fbSAlexey Lapshin     // The segment offset is generally the offset of the first section.
235925d7b4fbSAlexey Lapshin     //
236025d7b4fbSAlexey Lapshin     // For a segment containing no section (see sectionWithinSegment), if it has
236125d7b4fbSAlexey Lapshin     // a parent segment, copy the parent segment's offset field. This works for
236225d7b4fbSAlexey Lapshin     // empty PT_TLS. If no parent segment, use 0: the segment is not useful for
236325d7b4fbSAlexey Lapshin     // debugging anyway.
236425d7b4fbSAlexey Lapshin     const SectionBase *FirstSec = Seg->firstSection();
236525d7b4fbSAlexey Lapshin     uint64_t Offset =
236625d7b4fbSAlexey Lapshin         FirstSec ? FirstSec->Offset
236725d7b4fbSAlexey Lapshin                  : (Seg->ParentSegment ? Seg->ParentSegment->Offset : 0);
236825d7b4fbSAlexey Lapshin     uint64_t FileSize = 0;
236925d7b4fbSAlexey Lapshin     for (const SectionBase *Sec : Seg->Sections) {
237025d7b4fbSAlexey Lapshin       uint64_t Size = Sec->Type == SHT_NOBITS ? 0 : Sec->Size;
237125d7b4fbSAlexey Lapshin       if (Sec->Offset + Size > Offset)
237225d7b4fbSAlexey Lapshin         FileSize = std::max(FileSize, Sec->Offset + Size - Offset);
237325d7b4fbSAlexey Lapshin     }
237425d7b4fbSAlexey Lapshin 
237525d7b4fbSAlexey Lapshin     // If the segment includes EHDR and program headers, don't make it smaller
237625d7b4fbSAlexey Lapshin     // than the headers.
237725d7b4fbSAlexey Lapshin     if (Seg->Offset < HdrEnd && HdrEnd <= Seg->Offset + Seg->FileSize) {
237825d7b4fbSAlexey Lapshin       FileSize += Offset - Seg->Offset;
237925d7b4fbSAlexey Lapshin       Offset = Seg->Offset;
238025d7b4fbSAlexey Lapshin       FileSize = std::max(FileSize, HdrEnd - Offset);
238125d7b4fbSAlexey Lapshin     }
238225d7b4fbSAlexey Lapshin 
238325d7b4fbSAlexey Lapshin     Seg->Offset = Offset;
238425d7b4fbSAlexey Lapshin     Seg->FileSize = FileSize;
238525d7b4fbSAlexey Lapshin     MaxOffset = std::max(MaxOffset, Offset + FileSize);
238625d7b4fbSAlexey Lapshin   }
238725d7b4fbSAlexey Lapshin   return MaxOffset;
238825d7b4fbSAlexey Lapshin }
238925d7b4fbSAlexey Lapshin 
initEhdrSegment()239025d7b4fbSAlexey Lapshin template <class ELFT> void ELFWriter<ELFT>::initEhdrSegment() {
239125d7b4fbSAlexey Lapshin   Segment &ElfHdr = Obj.ElfHdrSegment;
239225d7b4fbSAlexey Lapshin   ElfHdr.Type = PT_PHDR;
239325d7b4fbSAlexey Lapshin   ElfHdr.Flags = 0;
239425d7b4fbSAlexey Lapshin   ElfHdr.VAddr = 0;
239525d7b4fbSAlexey Lapshin   ElfHdr.PAddr = 0;
239625d7b4fbSAlexey Lapshin   ElfHdr.FileSize = ElfHdr.MemSize = sizeof(Elf_Ehdr);
239725d7b4fbSAlexey Lapshin   ElfHdr.Align = 0;
239825d7b4fbSAlexey Lapshin }
239925d7b4fbSAlexey Lapshin 
assignOffsets()240025d7b4fbSAlexey Lapshin template <class ELFT> void ELFWriter<ELFT>::assignOffsets() {
240125d7b4fbSAlexey Lapshin   // We need a temporary list of segments that has a special order to it
240225d7b4fbSAlexey Lapshin   // so that we know that anytime ->ParentSegment is set that segment has
240325d7b4fbSAlexey Lapshin   // already had its offset properly set.
240425d7b4fbSAlexey Lapshin   std::vector<Segment *> OrderedSegments;
240525d7b4fbSAlexey Lapshin   for (Segment &Segment : Obj.segments())
240625d7b4fbSAlexey Lapshin     OrderedSegments.push_back(&Segment);
240725d7b4fbSAlexey Lapshin   OrderedSegments.push_back(&Obj.ElfHdrSegment);
240825d7b4fbSAlexey Lapshin   OrderedSegments.push_back(&Obj.ProgramHdrSegment);
240925d7b4fbSAlexey Lapshin   orderSegments(OrderedSegments);
241025d7b4fbSAlexey Lapshin 
241125d7b4fbSAlexey Lapshin   uint64_t Offset;
241225d7b4fbSAlexey Lapshin   if (OnlyKeepDebug) {
241325d7b4fbSAlexey Lapshin     // For --only-keep-debug, the sections that did not preserve contents were
241425d7b4fbSAlexey Lapshin     // changed to SHT_NOBITS. We now rewrite sh_offset fields of sections, and
241525d7b4fbSAlexey Lapshin     // then rewrite p_offset/p_filesz of program headers.
241625d7b4fbSAlexey Lapshin     uint64_t HdrEnd =
241725d7b4fbSAlexey Lapshin         sizeof(Elf_Ehdr) + llvm::size(Obj.segments()) * sizeof(Elf_Phdr);
241825d7b4fbSAlexey Lapshin     Offset = layoutSectionsForOnlyKeepDebug(Obj, HdrEnd);
241925d7b4fbSAlexey Lapshin     Offset = std::max(Offset,
242025d7b4fbSAlexey Lapshin                       layoutSegmentsForOnlyKeepDebug(OrderedSegments, HdrEnd));
242125d7b4fbSAlexey Lapshin   } else {
242225d7b4fbSAlexey Lapshin     // Offset is used as the start offset of the first segment to be laid out.
242325d7b4fbSAlexey Lapshin     // Since the ELF Header (ElfHdrSegment) must be at the start of the file,
242425d7b4fbSAlexey Lapshin     // we start at offset 0.
242525d7b4fbSAlexey Lapshin     Offset = layoutSegments(OrderedSegments, 0);
242625d7b4fbSAlexey Lapshin     Offset = layoutSections(Obj.sections(), Offset);
242725d7b4fbSAlexey Lapshin   }
242825d7b4fbSAlexey Lapshin   // If we need to write the section header table out then we need to align the
242925d7b4fbSAlexey Lapshin   // Offset so that SHOffset is valid.
243025d7b4fbSAlexey Lapshin   if (WriteSectionHeaders)
243125d7b4fbSAlexey Lapshin     Offset = alignTo(Offset, sizeof(Elf_Addr));
243225d7b4fbSAlexey Lapshin   Obj.SHOff = Offset;
243325d7b4fbSAlexey Lapshin }
243425d7b4fbSAlexey Lapshin 
totalSize() const243525d7b4fbSAlexey Lapshin template <class ELFT> size_t ELFWriter<ELFT>::totalSize() const {
243625d7b4fbSAlexey Lapshin   // We already have the section header offset so we can calculate the total
243725d7b4fbSAlexey Lapshin   // size by just adding up the size of each section header.
243825d7b4fbSAlexey Lapshin   if (!WriteSectionHeaders)
243925d7b4fbSAlexey Lapshin     return Obj.SHOff;
244025d7b4fbSAlexey Lapshin   size_t ShdrCount = Obj.sections().size() + 1; // Includes null shdr.
244125d7b4fbSAlexey Lapshin   return Obj.SHOff + ShdrCount * sizeof(Elf_Shdr);
244225d7b4fbSAlexey Lapshin }
244325d7b4fbSAlexey Lapshin 
write()244425d7b4fbSAlexey Lapshin template <class ELFT> Error ELFWriter<ELFT>::write() {
244525d7b4fbSAlexey Lapshin   // Segment data must be written first, so that the ELF header and program
244625d7b4fbSAlexey Lapshin   // header tables can overwrite it, if covered by a segment.
244725d7b4fbSAlexey Lapshin   writeSegmentData();
244825d7b4fbSAlexey Lapshin   writeEhdr();
244925d7b4fbSAlexey Lapshin   writePhdrs();
245025d7b4fbSAlexey Lapshin   if (Error E = writeSectionData())
245125d7b4fbSAlexey Lapshin     return E;
245225d7b4fbSAlexey Lapshin   if (WriteSectionHeaders)
245325d7b4fbSAlexey Lapshin     writeShdrs();
245425d7b4fbSAlexey Lapshin 
245525d7b4fbSAlexey Lapshin   // TODO: Implement direct writing to the output stream (without intermediate
245625d7b4fbSAlexey Lapshin   // memory buffer Buf).
245725d7b4fbSAlexey Lapshin   Out.write(Buf->getBufferStart(), Buf->getBufferSize());
245825d7b4fbSAlexey Lapshin   return Error::success();
245925d7b4fbSAlexey Lapshin }
246025d7b4fbSAlexey Lapshin 
removeUnneededSections(Object & Obj)246125d7b4fbSAlexey Lapshin static Error removeUnneededSections(Object &Obj) {
246225d7b4fbSAlexey Lapshin   // We can remove an empty symbol table from non-relocatable objects.
246325d7b4fbSAlexey Lapshin   // Relocatable objects typically have relocation sections whose
246425d7b4fbSAlexey Lapshin   // sh_link field points to .symtab, so we can't remove .symtab
246525d7b4fbSAlexey Lapshin   // even if it is empty.
246625d7b4fbSAlexey Lapshin   if (Obj.isRelocatable() || Obj.SymbolTable == nullptr ||
246725d7b4fbSAlexey Lapshin       !Obj.SymbolTable->empty())
246825d7b4fbSAlexey Lapshin     return Error::success();
246925d7b4fbSAlexey Lapshin 
247025d7b4fbSAlexey Lapshin   // .strtab can be used for section names. In such a case we shouldn't
247125d7b4fbSAlexey Lapshin   // remove it.
247225d7b4fbSAlexey Lapshin   auto *StrTab = Obj.SymbolTable->getStrTab() == Obj.SectionNames
247325d7b4fbSAlexey Lapshin                      ? nullptr
247425d7b4fbSAlexey Lapshin                      : Obj.SymbolTable->getStrTab();
247525d7b4fbSAlexey Lapshin   return Obj.removeSections(false, [&](const SectionBase &Sec) {
247625d7b4fbSAlexey Lapshin     return &Sec == Obj.SymbolTable || &Sec == StrTab;
247725d7b4fbSAlexey Lapshin   });
247825d7b4fbSAlexey Lapshin }
247925d7b4fbSAlexey Lapshin 
finalize()248025d7b4fbSAlexey Lapshin template <class ELFT> Error ELFWriter<ELFT>::finalize() {
248125d7b4fbSAlexey Lapshin   // It could happen that SectionNames has been removed and yet the user wants
248225d7b4fbSAlexey Lapshin   // a section header table output. We need to throw an error if a user tries
248325d7b4fbSAlexey Lapshin   // to do that.
248425d7b4fbSAlexey Lapshin   if (Obj.SectionNames == nullptr && WriteSectionHeaders)
248525d7b4fbSAlexey Lapshin     return createStringError(llvm::errc::invalid_argument,
248625d7b4fbSAlexey Lapshin                              "cannot write section header table because "
248725d7b4fbSAlexey Lapshin                              "section header string table was removed");
248825d7b4fbSAlexey Lapshin 
248925d7b4fbSAlexey Lapshin   if (Error E = removeUnneededSections(Obj))
249025d7b4fbSAlexey Lapshin     return E;
249125d7b4fbSAlexey Lapshin 
249225d7b4fbSAlexey Lapshin   // We need to assign indexes before we perform layout because we need to know
249325d7b4fbSAlexey Lapshin   // if we need large indexes or not. We can assign indexes first and check as
249425d7b4fbSAlexey Lapshin   // we go to see if we will actully need large indexes.
249525d7b4fbSAlexey Lapshin   bool NeedsLargeIndexes = false;
249625d7b4fbSAlexey Lapshin   if (Obj.sections().size() >= SHN_LORESERVE) {
249725d7b4fbSAlexey Lapshin     SectionTableRef Sections = Obj.sections();
249825d7b4fbSAlexey Lapshin     // Sections doesn't include the null section header, so account for this
249925d7b4fbSAlexey Lapshin     // when skipping the first N sections.
250025d7b4fbSAlexey Lapshin     NeedsLargeIndexes =
250125d7b4fbSAlexey Lapshin         any_of(drop_begin(Sections, SHN_LORESERVE - 1),
250225d7b4fbSAlexey Lapshin                [](const SectionBase &Sec) { return Sec.HasSymbol; });
250325d7b4fbSAlexey Lapshin     // TODO: handle case where only one section needs the large index table but
250425d7b4fbSAlexey Lapshin     // only needs it because the large index table hasn't been removed yet.
250525d7b4fbSAlexey Lapshin   }
250625d7b4fbSAlexey Lapshin 
250725d7b4fbSAlexey Lapshin   if (NeedsLargeIndexes) {
250825d7b4fbSAlexey Lapshin     // This means we definitely need to have a section index table but if we
250925d7b4fbSAlexey Lapshin     // already have one then we should use it instead of making a new one.
251025d7b4fbSAlexey Lapshin     if (Obj.SymbolTable != nullptr && Obj.SectionIndexTable == nullptr) {
251125d7b4fbSAlexey Lapshin       // Addition of a section to the end does not invalidate the indexes of
251225d7b4fbSAlexey Lapshin       // other sections and assigns the correct index to the new section.
251325d7b4fbSAlexey Lapshin       auto &Shndx = Obj.addSection<SectionIndexSection>();
251425d7b4fbSAlexey Lapshin       Obj.SymbolTable->setShndxTable(&Shndx);
251525d7b4fbSAlexey Lapshin       Shndx.setSymTab(Obj.SymbolTable);
251625d7b4fbSAlexey Lapshin     }
251725d7b4fbSAlexey Lapshin   } else {
251825d7b4fbSAlexey Lapshin     // Since we don't need SectionIndexTable we should remove it and all
251925d7b4fbSAlexey Lapshin     // references to it.
252025d7b4fbSAlexey Lapshin     if (Obj.SectionIndexTable != nullptr) {
252125d7b4fbSAlexey Lapshin       // We do not support sections referring to the section index table.
252225d7b4fbSAlexey Lapshin       if (Error E = Obj.removeSections(false /*AllowBrokenLinks*/,
252325d7b4fbSAlexey Lapshin                                        [this](const SectionBase &Sec) {
252425d7b4fbSAlexey Lapshin                                          return &Sec == Obj.SectionIndexTable;
252525d7b4fbSAlexey Lapshin                                        }))
252625d7b4fbSAlexey Lapshin         return E;
252725d7b4fbSAlexey Lapshin     }
252825d7b4fbSAlexey Lapshin   }
252925d7b4fbSAlexey Lapshin 
253025d7b4fbSAlexey Lapshin   // Make sure we add the names of all the sections. Importantly this must be
253125d7b4fbSAlexey Lapshin   // done after we decide to add or remove SectionIndexes.
253225d7b4fbSAlexey Lapshin   if (Obj.SectionNames != nullptr)
253325d7b4fbSAlexey Lapshin     for (const SectionBase &Sec : Obj.sections())
253425d7b4fbSAlexey Lapshin       Obj.SectionNames->addString(Sec.Name);
253525d7b4fbSAlexey Lapshin 
253625d7b4fbSAlexey Lapshin   initEhdrSegment();
253725d7b4fbSAlexey Lapshin 
253825d7b4fbSAlexey Lapshin   // Before we can prepare for layout the indexes need to be finalized.
253925d7b4fbSAlexey Lapshin   // Also, the output arch may not be the same as the input arch, so fix up
254025d7b4fbSAlexey Lapshin   // size-related fields before doing layout calculations.
254125d7b4fbSAlexey Lapshin   uint64_t Index = 0;
254225d7b4fbSAlexey Lapshin   auto SecSizer = std::make_unique<ELFSectionSizer<ELFT>>();
254325d7b4fbSAlexey Lapshin   for (SectionBase &Sec : Obj.sections()) {
254425d7b4fbSAlexey Lapshin     Sec.Index = Index++;
254525d7b4fbSAlexey Lapshin     if (Error Err = Sec.accept(*SecSizer))
254625d7b4fbSAlexey Lapshin       return Err;
254725d7b4fbSAlexey Lapshin   }
254825d7b4fbSAlexey Lapshin 
254925d7b4fbSAlexey Lapshin   // The symbol table does not update all other sections on update. For
255025d7b4fbSAlexey Lapshin   // instance, symbol names are not added as new symbols are added. This means
255125d7b4fbSAlexey Lapshin   // that some sections, like .strtab, don't yet have their final size.
255225d7b4fbSAlexey Lapshin   if (Obj.SymbolTable != nullptr)
255325d7b4fbSAlexey Lapshin     Obj.SymbolTable->prepareForLayout();
255425d7b4fbSAlexey Lapshin 
255525d7b4fbSAlexey Lapshin   // Now that all strings are added we want to finalize string table builders,
255625d7b4fbSAlexey Lapshin   // because that affects section sizes which in turn affects section offsets.
255725d7b4fbSAlexey Lapshin   for (SectionBase &Sec : Obj.sections())
255825d7b4fbSAlexey Lapshin     if (auto StrTab = dyn_cast<StringTableSection>(&Sec))
255925d7b4fbSAlexey Lapshin       StrTab->prepareForLayout();
256025d7b4fbSAlexey Lapshin 
256125d7b4fbSAlexey Lapshin   assignOffsets();
256225d7b4fbSAlexey Lapshin 
256325d7b4fbSAlexey Lapshin   // layoutSections could have modified section indexes, so we need
256425d7b4fbSAlexey Lapshin   // to fill the index table after assignOffsets.
256525d7b4fbSAlexey Lapshin   if (Obj.SymbolTable != nullptr)
256625d7b4fbSAlexey Lapshin     Obj.SymbolTable->fillShndxTable();
256725d7b4fbSAlexey Lapshin 
256825d7b4fbSAlexey Lapshin   // Finally now that all offsets and indexes have been set we can finalize any
256925d7b4fbSAlexey Lapshin   // remaining issues.
257025d7b4fbSAlexey Lapshin   uint64_t Offset = Obj.SHOff + sizeof(Elf_Shdr);
257125d7b4fbSAlexey Lapshin   for (SectionBase &Sec : Obj.sections()) {
257225d7b4fbSAlexey Lapshin     Sec.HeaderOffset = Offset;
257325d7b4fbSAlexey Lapshin     Offset += sizeof(Elf_Shdr);
257425d7b4fbSAlexey Lapshin     if (WriteSectionHeaders)
257525d7b4fbSAlexey Lapshin       Sec.NameIndex = Obj.SectionNames->findIndex(Sec.Name);
257625d7b4fbSAlexey Lapshin     Sec.finalize();
257725d7b4fbSAlexey Lapshin   }
257825d7b4fbSAlexey Lapshin 
257925d7b4fbSAlexey Lapshin   size_t TotalSize = totalSize();
258025d7b4fbSAlexey Lapshin   Buf = WritableMemoryBuffer::getNewMemBuffer(TotalSize);
258125d7b4fbSAlexey Lapshin   if (!Buf)
258225d7b4fbSAlexey Lapshin     return createStringError(errc::not_enough_memory,
258325d7b4fbSAlexey Lapshin                              "failed to allocate memory buffer of " +
258425d7b4fbSAlexey Lapshin                                  Twine::utohexstr(TotalSize) + " bytes");
258525d7b4fbSAlexey Lapshin 
258625d7b4fbSAlexey Lapshin   SecWriter = std::make_unique<ELFSectionWriter<ELFT>>(*Buf);
258725d7b4fbSAlexey Lapshin   return Error::success();
258825d7b4fbSAlexey Lapshin }
258925d7b4fbSAlexey Lapshin 
write()259025d7b4fbSAlexey Lapshin Error BinaryWriter::write() {
259125d7b4fbSAlexey Lapshin   for (const SectionBase &Sec : Obj.allocSections())
259225d7b4fbSAlexey Lapshin     if (Error Err = Sec.accept(*SecWriter))
259325d7b4fbSAlexey Lapshin       return Err;
259425d7b4fbSAlexey Lapshin 
259525d7b4fbSAlexey Lapshin   // TODO: Implement direct writing to the output stream (without intermediate
259625d7b4fbSAlexey Lapshin   // memory buffer Buf).
259725d7b4fbSAlexey Lapshin   Out.write(Buf->getBufferStart(), Buf->getBufferSize());
259825d7b4fbSAlexey Lapshin   return Error::success();
259925d7b4fbSAlexey Lapshin }
260025d7b4fbSAlexey Lapshin 
finalize()260125d7b4fbSAlexey Lapshin Error BinaryWriter::finalize() {
260225d7b4fbSAlexey Lapshin   // Compute the section LMA based on its sh_offset and the containing segment's
260325d7b4fbSAlexey Lapshin   // p_offset and p_paddr. Also compute the minimum LMA of all non-empty
260425d7b4fbSAlexey Lapshin   // sections as MinAddr. In the output, the contents between address 0 and
260525d7b4fbSAlexey Lapshin   // MinAddr will be skipped.
260625d7b4fbSAlexey Lapshin   uint64_t MinAddr = UINT64_MAX;
260725d7b4fbSAlexey Lapshin   for (SectionBase &Sec : Obj.allocSections()) {
26080c01f42fSFangrui Song     // If Sec's type is changed from SHT_NOBITS due to --set-section-flags,
26090c01f42fSFangrui Song     // Offset may not be aligned. Align it to max(Align, 1).
261025d7b4fbSAlexey Lapshin     if (Sec.ParentSegment != nullptr)
26110c01f42fSFangrui Song       Sec.Addr = alignTo(Sec.Offset - Sec.ParentSegment->Offset +
26120c01f42fSFangrui Song                              Sec.ParentSegment->PAddr,
26130c01f42fSFangrui Song                          std::max(Sec.Align, uint64_t(1)));
261425d7b4fbSAlexey Lapshin     if (Sec.Type != SHT_NOBITS && Sec.Size > 0)
261525d7b4fbSAlexey Lapshin       MinAddr = std::min(MinAddr, Sec.Addr);
261625d7b4fbSAlexey Lapshin   }
261725d7b4fbSAlexey Lapshin 
261825d7b4fbSAlexey Lapshin   // Now that every section has been laid out we just need to compute the total
261925d7b4fbSAlexey Lapshin   // file size. This might not be the same as the offset returned by
262025d7b4fbSAlexey Lapshin   // layoutSections, because we want to truncate the last segment to the end of
262125d7b4fbSAlexey Lapshin   // its last non-empty section, to match GNU objcopy's behaviour.
262225d7b4fbSAlexey Lapshin   TotalSize = 0;
262325d7b4fbSAlexey Lapshin   for (SectionBase &Sec : Obj.allocSections())
262425d7b4fbSAlexey Lapshin     if (Sec.Type != SHT_NOBITS && Sec.Size > 0) {
262525d7b4fbSAlexey Lapshin       Sec.Offset = Sec.Addr - MinAddr;
262625d7b4fbSAlexey Lapshin       TotalSize = std::max(TotalSize, Sec.Offset + Sec.Size);
262725d7b4fbSAlexey Lapshin     }
262825d7b4fbSAlexey Lapshin 
262925d7b4fbSAlexey Lapshin   Buf = WritableMemoryBuffer::getNewMemBuffer(TotalSize);
263025d7b4fbSAlexey Lapshin   if (!Buf)
263125d7b4fbSAlexey Lapshin     return createStringError(errc::not_enough_memory,
263225d7b4fbSAlexey Lapshin                              "failed to allocate memory buffer of " +
263325d7b4fbSAlexey Lapshin                                  Twine::utohexstr(TotalSize) + " bytes");
263425d7b4fbSAlexey Lapshin   SecWriter = std::make_unique<BinarySectionWriter>(*Buf);
263525d7b4fbSAlexey Lapshin   return Error::success();
263625d7b4fbSAlexey Lapshin }
263725d7b4fbSAlexey Lapshin 
operator ()(const SectionBase * Lhs,const SectionBase * Rhs) const263825d7b4fbSAlexey Lapshin bool IHexWriter::SectionCompare::operator()(const SectionBase *Lhs,
263925d7b4fbSAlexey Lapshin                                             const SectionBase *Rhs) const {
264025d7b4fbSAlexey Lapshin   return (sectionPhysicalAddr(Lhs) & 0xFFFFFFFFU) <
264125d7b4fbSAlexey Lapshin          (sectionPhysicalAddr(Rhs) & 0xFFFFFFFFU);
264225d7b4fbSAlexey Lapshin }
264325d7b4fbSAlexey Lapshin 
writeEntryPointRecord(uint8_t * Buf)264425d7b4fbSAlexey Lapshin uint64_t IHexWriter::writeEntryPointRecord(uint8_t *Buf) {
264525d7b4fbSAlexey Lapshin   IHexLineData HexData;
264625d7b4fbSAlexey Lapshin   uint8_t Data[4] = {};
264725d7b4fbSAlexey Lapshin   // We don't write entry point record if entry is zero.
264825d7b4fbSAlexey Lapshin   if (Obj.Entry == 0)
264925d7b4fbSAlexey Lapshin     return 0;
265025d7b4fbSAlexey Lapshin 
265125d7b4fbSAlexey Lapshin   if (Obj.Entry <= 0xFFFFFU) {
265225d7b4fbSAlexey Lapshin     Data[0] = ((Obj.Entry & 0xF0000U) >> 12) & 0xFF;
265325d7b4fbSAlexey Lapshin     support::endian::write(&Data[2], static_cast<uint16_t>(Obj.Entry),
265425d7b4fbSAlexey Lapshin                            support::big);
265525d7b4fbSAlexey Lapshin     HexData = IHexRecord::getLine(IHexRecord::StartAddr80x86, 0, Data);
265625d7b4fbSAlexey Lapshin   } else {
265725d7b4fbSAlexey Lapshin     support::endian::write(Data, static_cast<uint32_t>(Obj.Entry),
265825d7b4fbSAlexey Lapshin                            support::big);
265925d7b4fbSAlexey Lapshin     HexData = IHexRecord::getLine(IHexRecord::StartAddr, 0, Data);
266025d7b4fbSAlexey Lapshin   }
266125d7b4fbSAlexey Lapshin   memcpy(Buf, HexData.data(), HexData.size());
266225d7b4fbSAlexey Lapshin   return HexData.size();
266325d7b4fbSAlexey Lapshin }
266425d7b4fbSAlexey Lapshin 
writeEndOfFileRecord(uint8_t * Buf)266525d7b4fbSAlexey Lapshin uint64_t IHexWriter::writeEndOfFileRecord(uint8_t *Buf) {
266625d7b4fbSAlexey Lapshin   IHexLineData HexData = IHexRecord::getLine(IHexRecord::EndOfFile, 0, {});
266725d7b4fbSAlexey Lapshin   memcpy(Buf, HexData.data(), HexData.size());
266825d7b4fbSAlexey Lapshin   return HexData.size();
266925d7b4fbSAlexey Lapshin }
267025d7b4fbSAlexey Lapshin 
write()267125d7b4fbSAlexey Lapshin Error IHexWriter::write() {
267225d7b4fbSAlexey Lapshin   IHexSectionWriter Writer(*Buf);
267325d7b4fbSAlexey Lapshin   // Write sections.
267425d7b4fbSAlexey Lapshin   for (const SectionBase *Sec : Sections)
267525d7b4fbSAlexey Lapshin     if (Error Err = Sec->accept(Writer))
267625d7b4fbSAlexey Lapshin       return Err;
267725d7b4fbSAlexey Lapshin 
267825d7b4fbSAlexey Lapshin   uint64_t Offset = Writer.getBufferOffset();
267925d7b4fbSAlexey Lapshin   // Write entry point address.
268025d7b4fbSAlexey Lapshin   Offset += writeEntryPointRecord(
268125d7b4fbSAlexey Lapshin       reinterpret_cast<uint8_t *>(Buf->getBufferStart()) + Offset);
268225d7b4fbSAlexey Lapshin   // Write EOF.
268325d7b4fbSAlexey Lapshin   Offset += writeEndOfFileRecord(
268425d7b4fbSAlexey Lapshin       reinterpret_cast<uint8_t *>(Buf->getBufferStart()) + Offset);
268525d7b4fbSAlexey Lapshin   assert(Offset == TotalSize);
268625d7b4fbSAlexey Lapshin 
268725d7b4fbSAlexey Lapshin   // TODO: Implement direct writing to the output stream (without intermediate
268825d7b4fbSAlexey Lapshin   // memory buffer Buf).
268925d7b4fbSAlexey Lapshin   Out.write(Buf->getBufferStart(), Buf->getBufferSize());
269025d7b4fbSAlexey Lapshin   return Error::success();
269125d7b4fbSAlexey Lapshin }
269225d7b4fbSAlexey Lapshin 
checkSection(const SectionBase & Sec)269325d7b4fbSAlexey Lapshin Error IHexWriter::checkSection(const SectionBase &Sec) {
269425d7b4fbSAlexey Lapshin   uint64_t Addr = sectionPhysicalAddr(&Sec);
269525d7b4fbSAlexey Lapshin   if (addressOverflows32bit(Addr) || addressOverflows32bit(Addr + Sec.Size - 1))
269625d7b4fbSAlexey Lapshin     return createStringError(
269725d7b4fbSAlexey Lapshin         errc::invalid_argument,
269825d7b4fbSAlexey Lapshin         "Section '%s' address range [0x%llx, 0x%llx] is not 32 bit",
269925d7b4fbSAlexey Lapshin         Sec.Name.c_str(), Addr, Addr + Sec.Size - 1);
270025d7b4fbSAlexey Lapshin   return Error::success();
270125d7b4fbSAlexey Lapshin }
270225d7b4fbSAlexey Lapshin 
finalize()270325d7b4fbSAlexey Lapshin Error IHexWriter::finalize() {
270425d7b4fbSAlexey Lapshin   // We can't write 64-bit addresses.
270525d7b4fbSAlexey Lapshin   if (addressOverflows32bit(Obj.Entry))
270625d7b4fbSAlexey Lapshin     return createStringError(errc::invalid_argument,
270725d7b4fbSAlexey Lapshin                              "Entry point address 0x%llx overflows 32 bits",
270825d7b4fbSAlexey Lapshin                              Obj.Entry);
270925d7b4fbSAlexey Lapshin 
271025d7b4fbSAlexey Lapshin   for (const SectionBase &Sec : Obj.sections())
271125d7b4fbSAlexey Lapshin     if ((Sec.Flags & ELF::SHF_ALLOC) && Sec.Type != ELF::SHT_NOBITS &&
271225d7b4fbSAlexey Lapshin         Sec.Size > 0) {
271325d7b4fbSAlexey Lapshin       if (Error E = checkSection(Sec))
271425d7b4fbSAlexey Lapshin         return E;
271525d7b4fbSAlexey Lapshin       Sections.insert(&Sec);
271625d7b4fbSAlexey Lapshin     }
271725d7b4fbSAlexey Lapshin 
271825d7b4fbSAlexey Lapshin   std::unique_ptr<WritableMemoryBuffer> EmptyBuffer =
271925d7b4fbSAlexey Lapshin       WritableMemoryBuffer::getNewMemBuffer(0);
272025d7b4fbSAlexey Lapshin   if (!EmptyBuffer)
272125d7b4fbSAlexey Lapshin     return createStringError(errc::not_enough_memory,
272225d7b4fbSAlexey Lapshin                              "failed to allocate memory buffer of 0 bytes");
272325d7b4fbSAlexey Lapshin 
272425d7b4fbSAlexey Lapshin   IHexSectionWriterBase LengthCalc(*EmptyBuffer);
272525d7b4fbSAlexey Lapshin   for (const SectionBase *Sec : Sections)
272625d7b4fbSAlexey Lapshin     if (Error Err = Sec->accept(LengthCalc))
272725d7b4fbSAlexey Lapshin       return Err;
272825d7b4fbSAlexey Lapshin 
272925d7b4fbSAlexey Lapshin   // We need space to write section records + StartAddress record
273025d7b4fbSAlexey Lapshin   // (if start adress is not zero) + EndOfFile record.
273125d7b4fbSAlexey Lapshin   TotalSize = LengthCalc.getBufferOffset() +
273225d7b4fbSAlexey Lapshin               (Obj.Entry ? IHexRecord::getLineLength(4) : 0) +
273325d7b4fbSAlexey Lapshin               IHexRecord::getLineLength(0);
273425d7b4fbSAlexey Lapshin 
273525d7b4fbSAlexey Lapshin   Buf = WritableMemoryBuffer::getNewMemBuffer(TotalSize);
273625d7b4fbSAlexey Lapshin   if (!Buf)
273725d7b4fbSAlexey Lapshin     return createStringError(errc::not_enough_memory,
273825d7b4fbSAlexey Lapshin                              "failed to allocate memory buffer of " +
273925d7b4fbSAlexey Lapshin                                  Twine::utohexstr(TotalSize) + " bytes");
274025d7b4fbSAlexey Lapshin 
274125d7b4fbSAlexey Lapshin   return Error::success();
274225d7b4fbSAlexey Lapshin }
274325d7b4fbSAlexey Lapshin 
274425d7b4fbSAlexey Lapshin namespace llvm {
274525d7b4fbSAlexey Lapshin namespace objcopy {
274625d7b4fbSAlexey Lapshin namespace elf {
274725d7b4fbSAlexey Lapshin 
274825d7b4fbSAlexey Lapshin template class ELFBuilder<ELF64LE>;
274925d7b4fbSAlexey Lapshin template class ELFBuilder<ELF64BE>;
275025d7b4fbSAlexey Lapshin template class ELFBuilder<ELF32LE>;
275125d7b4fbSAlexey Lapshin template class ELFBuilder<ELF32BE>;
275225d7b4fbSAlexey Lapshin 
275325d7b4fbSAlexey Lapshin template class ELFWriter<ELF64LE>;
275425d7b4fbSAlexey Lapshin template class ELFWriter<ELF64BE>;
275525d7b4fbSAlexey Lapshin template class ELFWriter<ELF32LE>;
275625d7b4fbSAlexey Lapshin template class ELFWriter<ELF32BE>;
275725d7b4fbSAlexey Lapshin 
275825d7b4fbSAlexey Lapshin } // end namespace elf
275925d7b4fbSAlexey Lapshin } // end namespace objcopy
276025d7b4fbSAlexey Lapshin } // end namespace llvm
2761