Path: blob/main/contrib/llvm-project/llvm/lib/ObjCopy/ELF/ELFObject.cpp
35266 views
//===- ELFObject.cpp ------------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "ELFObject.h"9#include "llvm/ADT/ArrayRef.h"10#include "llvm/ADT/STLExtras.h"11#include "llvm/ADT/StringRef.h"12#include "llvm/ADT/Twine.h"13#include "llvm/ADT/iterator_range.h"14#include "llvm/BinaryFormat/ELF.h"15#include "llvm/MC/MCELFExtras.h"16#include "llvm/MC/MCTargetOptions.h"17#include "llvm/Object/ELF.h"18#include "llvm/Object/ELFObjectFile.h"19#include "llvm/Support/Compression.h"20#include "llvm/Support/Endian.h"21#include "llvm/Support/ErrorHandling.h"22#include "llvm/Support/FileOutputBuffer.h"23#include "llvm/Support/Path.h"24#include <algorithm>25#include <cstddef>26#include <cstdint>27#include <iterator>28#include <unordered_set>29#include <utility>30#include <vector>3132using namespace llvm;33using namespace llvm::ELF;34using namespace llvm::objcopy::elf;35using namespace llvm::object;36using namespace llvm::support;3738template <class ELFT> void ELFWriter<ELFT>::writePhdr(const Segment &Seg) {39uint8_t *B = reinterpret_cast<uint8_t *>(Buf->getBufferStart()) +40Obj.ProgramHdrSegment.Offset + Seg.Index * sizeof(Elf_Phdr);41Elf_Phdr &Phdr = *reinterpret_cast<Elf_Phdr *>(B);42Phdr.p_type = Seg.Type;43Phdr.p_flags = Seg.Flags;44Phdr.p_offset = Seg.Offset;45Phdr.p_vaddr = Seg.VAddr;46Phdr.p_paddr = Seg.PAddr;47Phdr.p_filesz = Seg.FileSize;48Phdr.p_memsz = Seg.MemSize;49Phdr.p_align = Seg.Align;50}5152Error SectionBase::removeSectionReferences(53bool, function_ref<bool(const SectionBase *)>) {54return Error::success();55}5657Error SectionBase::removeSymbols(function_ref<bool(const Symbol &)>) {58return Error::success();59}6061Error SectionBase::initialize(SectionTableRef) { return Error::success(); }62void SectionBase::finalize() {}63void SectionBase::markSymbols() {}64void SectionBase::replaceSectionReferences(65const DenseMap<SectionBase *, SectionBase *> &) {}66void SectionBase::onRemove() {}6768template <class ELFT> void ELFWriter<ELFT>::writeShdr(const SectionBase &Sec) {69uint8_t *B =70reinterpret_cast<uint8_t *>(Buf->getBufferStart()) + Sec.HeaderOffset;71Elf_Shdr &Shdr = *reinterpret_cast<Elf_Shdr *>(B);72Shdr.sh_name = Sec.NameIndex;73Shdr.sh_type = Sec.Type;74Shdr.sh_flags = Sec.Flags;75Shdr.sh_addr = Sec.Addr;76Shdr.sh_offset = Sec.Offset;77Shdr.sh_size = Sec.Size;78Shdr.sh_link = Sec.Link;79Shdr.sh_info = Sec.Info;80Shdr.sh_addralign = Sec.Align;81Shdr.sh_entsize = Sec.EntrySize;82}8384template <class ELFT> Error ELFSectionSizer<ELFT>::visit(Section &) {85return Error::success();86}8788template <class ELFT> Error ELFSectionSizer<ELFT>::visit(OwnedDataSection &) {89return Error::success();90}9192template <class ELFT> Error ELFSectionSizer<ELFT>::visit(StringTableSection &) {93return Error::success();94}9596template <class ELFT>97Error ELFSectionSizer<ELFT>::visit(DynamicRelocationSection &) {98return Error::success();99}100101template <class ELFT>102Error ELFSectionSizer<ELFT>::visit(SymbolTableSection &Sec) {103Sec.EntrySize = sizeof(Elf_Sym);104Sec.Size = Sec.Symbols.size() * Sec.EntrySize;105// Align to the largest field in Elf_Sym.106Sec.Align = ELFT::Is64Bits ? sizeof(Elf_Xword) : sizeof(Elf_Word);107return Error::success();108}109110template <bool Is64>111static SmallVector<char, 0> encodeCrel(ArrayRef<Relocation> Relocations) {112using uint = std::conditional_t<Is64, uint64_t, uint32_t>;113SmallVector<char, 0> Content;114raw_svector_ostream OS(Content);115ELF::encodeCrel<Is64>(OS, Relocations, [&](const Relocation &R) {116uint32_t CurSymIdx = R.RelocSymbol ? R.RelocSymbol->Index : 0;117return ELF::Elf_Crel<Is64>{static_cast<uint>(R.Offset), CurSymIdx, R.Type,118std::make_signed_t<uint>(R.Addend)};119});120return Content;121}122123template <class ELFT>124Error ELFSectionSizer<ELFT>::visit(RelocationSection &Sec) {125if (Sec.Type == SHT_CREL) {126Sec.Size = encodeCrel<ELFT::Is64Bits>(Sec.Relocations).size();127} else {128Sec.EntrySize = Sec.Type == SHT_REL ? sizeof(Elf_Rel) : sizeof(Elf_Rela);129Sec.Size = Sec.Relocations.size() * Sec.EntrySize;130// Align to the largest field in Elf_Rel(a).131Sec.Align = ELFT::Is64Bits ? sizeof(Elf_Xword) : sizeof(Elf_Word);132}133return Error::success();134}135136template <class ELFT>137Error ELFSectionSizer<ELFT>::visit(GnuDebugLinkSection &) {138return Error::success();139}140141template <class ELFT> Error ELFSectionSizer<ELFT>::visit(GroupSection &Sec) {142Sec.Size = sizeof(Elf_Word) + Sec.GroupMembers.size() * sizeof(Elf_Word);143return Error::success();144}145146template <class ELFT>147Error ELFSectionSizer<ELFT>::visit(SectionIndexSection &) {148return Error::success();149}150151template <class ELFT> Error ELFSectionSizer<ELFT>::visit(CompressedSection &) {152return Error::success();153}154155template <class ELFT>156Error ELFSectionSizer<ELFT>::visit(DecompressedSection &) {157return Error::success();158}159160Error BinarySectionWriter::visit(const SectionIndexSection &Sec) {161return createStringError(errc::operation_not_permitted,162"cannot write symbol section index table '" +163Sec.Name + "' ");164}165166Error BinarySectionWriter::visit(const SymbolTableSection &Sec) {167return createStringError(errc::operation_not_permitted,168"cannot write symbol table '" + Sec.Name +169"' out to binary");170}171172Error BinarySectionWriter::visit(const RelocationSection &Sec) {173return createStringError(errc::operation_not_permitted,174"cannot write relocation section '" + Sec.Name +175"' out to binary");176}177178Error BinarySectionWriter::visit(const GnuDebugLinkSection &Sec) {179return createStringError(errc::operation_not_permitted,180"cannot write '" + Sec.Name + "' out to binary");181}182183Error BinarySectionWriter::visit(const GroupSection &Sec) {184return createStringError(errc::operation_not_permitted,185"cannot write '" + Sec.Name + "' out to binary");186}187188Error SectionWriter::visit(const Section &Sec) {189if (Sec.Type != SHT_NOBITS)190llvm::copy(Sec.Contents, Out.getBufferStart() + Sec.Offset);191192return Error::success();193}194195static bool addressOverflows32bit(uint64_t Addr) {196// Sign extended 32 bit addresses (e.g 0xFFFFFFFF80000000) are ok197return Addr > UINT32_MAX && Addr + 0x80000000 > UINT32_MAX;198}199200template <class T> static T checkedGetHex(StringRef S) {201T Value;202bool Fail = S.getAsInteger(16, Value);203assert(!Fail);204(void)Fail;205return Value;206}207208// Fills exactly Len bytes of buffer with hexadecimal characters209// representing value 'X'210template <class T, class Iterator>211static Iterator toHexStr(T X, Iterator It, size_t Len) {212// Fill range with '0'213std::fill(It, It + Len, '0');214215for (long I = Len - 1; I >= 0; --I) {216unsigned char Mod = static_cast<unsigned char>(X) & 15;217*(It + I) = hexdigit(Mod, false);218X >>= 4;219}220assert(X == 0);221return It + Len;222}223224uint8_t IHexRecord::getChecksum(StringRef S) {225assert((S.size() & 1) == 0);226uint8_t Checksum = 0;227while (!S.empty()) {228Checksum += checkedGetHex<uint8_t>(S.take_front(2));229S = S.drop_front(2);230}231return -Checksum;232}233234IHexLineData IHexRecord::getLine(uint8_t Type, uint16_t Addr,235ArrayRef<uint8_t> Data) {236IHexLineData Line(getLineLength(Data.size()));237assert(Line.size());238auto Iter = Line.begin();239*Iter++ = ':';240Iter = toHexStr(Data.size(), Iter, 2);241Iter = toHexStr(Addr, Iter, 4);242Iter = toHexStr(Type, Iter, 2);243for (uint8_t X : Data)244Iter = toHexStr(X, Iter, 2);245StringRef S(Line.data() + 1, std::distance(Line.begin() + 1, Iter));246Iter = toHexStr(getChecksum(S), Iter, 2);247*Iter++ = '\r';248*Iter++ = '\n';249assert(Iter == Line.end());250return Line;251}252253static Error checkRecord(const IHexRecord &R) {254switch (R.Type) {255case IHexRecord::Data:256if (R.HexData.size() == 0)257return createStringError(258errc::invalid_argument,259"zero data length is not allowed for data records");260break;261case IHexRecord::EndOfFile:262break;263case IHexRecord::SegmentAddr:264// 20-bit segment address. Data length must be 2 bytes265// (4 bytes in hex)266if (R.HexData.size() != 4)267return createStringError(268errc::invalid_argument,269"segment address data should be 2 bytes in size");270break;271case IHexRecord::StartAddr80x86:272case IHexRecord::StartAddr:273if (R.HexData.size() != 8)274return createStringError(errc::invalid_argument,275"start address data should be 4 bytes in size");276// According to Intel HEX specification '03' record277// only specifies the code address within the 20-bit278// segmented address space of the 8086/80186. This279// means 12 high order bits should be zeroes.280if (R.Type == IHexRecord::StartAddr80x86 &&281R.HexData.take_front(3) != "000")282return createStringError(errc::invalid_argument,283"start address exceeds 20 bit for 80x86");284break;285case IHexRecord::ExtendedAddr:286// 16-31 bits of linear base address287if (R.HexData.size() != 4)288return createStringError(289errc::invalid_argument,290"extended address data should be 2 bytes in size");291break;292default:293// Unknown record type294return createStringError(errc::invalid_argument, "unknown record type: %u",295static_cast<unsigned>(R.Type));296}297return Error::success();298}299300// Checks that IHEX line contains valid characters.301// This allows converting hexadecimal data to integers302// without extra verification.303static Error checkChars(StringRef Line) {304assert(!Line.empty());305if (Line[0] != ':')306return createStringError(errc::invalid_argument,307"missing ':' in the beginning of line.");308309for (size_t Pos = 1; Pos < Line.size(); ++Pos)310if (hexDigitValue(Line[Pos]) == -1U)311return createStringError(errc::invalid_argument,312"invalid character at position %zu.", Pos + 1);313return Error::success();314}315316Expected<IHexRecord> IHexRecord::parse(StringRef Line) {317assert(!Line.empty());318319// ':' + Length + Address + Type + Checksum with empty data ':LLAAAATTCC'320if (Line.size() < 11)321return createStringError(errc::invalid_argument,322"line is too short: %zu chars.", Line.size());323324if (Error E = checkChars(Line))325return std::move(E);326327IHexRecord Rec;328size_t DataLen = checkedGetHex<uint8_t>(Line.substr(1, 2));329if (Line.size() != getLength(DataLen))330return createStringError(errc::invalid_argument,331"invalid line length %zu (should be %zu)",332Line.size(), getLength(DataLen));333334Rec.Addr = checkedGetHex<uint16_t>(Line.substr(3, 4));335Rec.Type = checkedGetHex<uint8_t>(Line.substr(7, 2));336Rec.HexData = Line.substr(9, DataLen * 2);337338if (getChecksum(Line.drop_front(1)) != 0)339return createStringError(errc::invalid_argument, "incorrect checksum.");340if (Error E = checkRecord(Rec))341return std::move(E);342return Rec;343}344345static uint64_t sectionPhysicalAddr(const SectionBase *Sec) {346Segment *Seg = Sec->ParentSegment;347if (Seg && Seg->Type != ELF::PT_LOAD)348Seg = nullptr;349return Seg ? Seg->PAddr + Sec->OriginalOffset - Seg->OriginalOffset350: Sec->Addr;351}352353void IHexSectionWriterBase::writeSection(const SectionBase *Sec,354ArrayRef<uint8_t> Data) {355assert(Data.size() == Sec->Size);356const uint32_t ChunkSize = 16;357uint32_t Addr = sectionPhysicalAddr(Sec) & 0xFFFFFFFFU;358while (!Data.empty()) {359uint64_t DataSize = std::min<uint64_t>(Data.size(), ChunkSize);360if (Addr > SegmentAddr + BaseAddr + 0xFFFFU) {361if (Addr > 0xFFFFFU) {362// Write extended address record, zeroing segment address363// if needed.364if (SegmentAddr != 0)365SegmentAddr = writeSegmentAddr(0U);366BaseAddr = writeBaseAddr(Addr);367} else {368// We can still remain 16-bit369SegmentAddr = writeSegmentAddr(Addr);370}371}372uint64_t SegOffset = Addr - BaseAddr - SegmentAddr;373assert(SegOffset <= 0xFFFFU);374DataSize = std::min(DataSize, 0x10000U - SegOffset);375writeData(0, SegOffset, Data.take_front(DataSize));376Addr += DataSize;377Data = Data.drop_front(DataSize);378}379}380381uint64_t IHexSectionWriterBase::writeSegmentAddr(uint64_t Addr) {382assert(Addr <= 0xFFFFFU);383uint8_t Data[] = {static_cast<uint8_t>((Addr & 0xF0000U) >> 12), 0};384writeData(2, 0, Data);385return Addr & 0xF0000U;386}387388uint64_t IHexSectionWriterBase::writeBaseAddr(uint64_t Addr) {389assert(Addr <= 0xFFFFFFFFU);390uint64_t Base = Addr & 0xFFFF0000U;391uint8_t Data[] = {static_cast<uint8_t>(Base >> 24),392static_cast<uint8_t>((Base >> 16) & 0xFF)};393writeData(4, 0, Data);394return Base;395}396397void IHexSectionWriterBase::writeData(uint8_t, uint16_t,398ArrayRef<uint8_t> Data) {399Offset += IHexRecord::getLineLength(Data.size());400}401402Error IHexSectionWriterBase::visit(const Section &Sec) {403writeSection(&Sec, Sec.Contents);404return Error::success();405}406407Error IHexSectionWriterBase::visit(const OwnedDataSection &Sec) {408writeSection(&Sec, Sec.Data);409return Error::success();410}411412Error IHexSectionWriterBase::visit(const StringTableSection &Sec) {413// Check that sizer has already done its work414assert(Sec.Size == Sec.StrTabBuilder.getSize());415// We are free to pass an invalid pointer to writeSection as long416// as we don't actually write any data. The real writer class has417// to override this method .418writeSection(&Sec, {nullptr, static_cast<size_t>(Sec.Size)});419return Error::success();420}421422Error IHexSectionWriterBase::visit(const DynamicRelocationSection &Sec) {423writeSection(&Sec, Sec.Contents);424return Error::success();425}426427void IHexSectionWriter::writeData(uint8_t Type, uint16_t Addr,428ArrayRef<uint8_t> Data) {429IHexLineData HexData = IHexRecord::getLine(Type, Addr, Data);430memcpy(Out.getBufferStart() + Offset, HexData.data(), HexData.size());431Offset += HexData.size();432}433434Error IHexSectionWriter::visit(const StringTableSection &Sec) {435assert(Sec.Size == Sec.StrTabBuilder.getSize());436std::vector<uint8_t> Data(Sec.Size);437Sec.StrTabBuilder.write(Data.data());438writeSection(&Sec, Data);439return Error::success();440}441442Error Section::accept(SectionVisitor &Visitor) const {443return Visitor.visit(*this);444}445446Error Section::accept(MutableSectionVisitor &Visitor) {447return Visitor.visit(*this);448}449450void Section::restoreSymTabLink(SymbolTableSection &SymTab) {451if (HasSymTabLink) {452assert(LinkSection == nullptr);453LinkSection = &SymTab;454}455}456457Error SectionWriter::visit(const OwnedDataSection &Sec) {458llvm::copy(Sec.Data, Out.getBufferStart() + Sec.Offset);459return Error::success();460}461462template <class ELFT>463Error ELFSectionWriter<ELFT>::visit(const DecompressedSection &Sec) {464ArrayRef<uint8_t> Compressed =465Sec.OriginalData.slice(sizeof(Elf_Chdr_Impl<ELFT>));466SmallVector<uint8_t, 128> Decompressed;467DebugCompressionType Type;468switch (Sec.ChType) {469case ELFCOMPRESS_ZLIB:470Type = DebugCompressionType::Zlib;471break;472case ELFCOMPRESS_ZSTD:473Type = DebugCompressionType::Zstd;474break;475default:476return createStringError(errc::invalid_argument,477"--decompress-debug-sections: ch_type (" +478Twine(Sec.ChType) + ") of section '" +479Sec.Name + "' is unsupported");480}481if (auto *Reason =482compression::getReasonIfUnsupported(compression::formatFor(Type)))483return createStringError(errc::invalid_argument,484"failed to decompress section '" + Sec.Name +485"': " + Reason);486if (Error E = compression::decompress(Type, Compressed, Decompressed,487static_cast<size_t>(Sec.Size)))488return createStringError(errc::invalid_argument,489"failed to decompress section '" + Sec.Name +490"': " + toString(std::move(E)));491492uint8_t *Buf = reinterpret_cast<uint8_t *>(Out.getBufferStart()) + Sec.Offset;493std::copy(Decompressed.begin(), Decompressed.end(), Buf);494495return Error::success();496}497498Error BinarySectionWriter::visit(const DecompressedSection &Sec) {499return createStringError(errc::operation_not_permitted,500"cannot write compressed section '" + Sec.Name +501"' ");502}503504Error DecompressedSection::accept(SectionVisitor &Visitor) const {505return Visitor.visit(*this);506}507508Error DecompressedSection::accept(MutableSectionVisitor &Visitor) {509return Visitor.visit(*this);510}511512Error OwnedDataSection::accept(SectionVisitor &Visitor) const {513return Visitor.visit(*this);514}515516Error OwnedDataSection::accept(MutableSectionVisitor &Visitor) {517return Visitor.visit(*this);518}519520void OwnedDataSection::appendHexData(StringRef HexData) {521assert((HexData.size() & 1) == 0);522while (!HexData.empty()) {523Data.push_back(checkedGetHex<uint8_t>(HexData.take_front(2)));524HexData = HexData.drop_front(2);525}526Size = Data.size();527}528529Error BinarySectionWriter::visit(const CompressedSection &Sec) {530return createStringError(errc::operation_not_permitted,531"cannot write compressed section '" + Sec.Name +532"' ");533}534535template <class ELFT>536Error ELFSectionWriter<ELFT>::visit(const CompressedSection &Sec) {537uint8_t *Buf = reinterpret_cast<uint8_t *>(Out.getBufferStart()) + Sec.Offset;538Elf_Chdr_Impl<ELFT> Chdr = {};539switch (Sec.CompressionType) {540case DebugCompressionType::None:541std::copy(Sec.OriginalData.begin(), Sec.OriginalData.end(), Buf);542return Error::success();543case DebugCompressionType::Zlib:544Chdr.ch_type = ELF::ELFCOMPRESS_ZLIB;545break;546case DebugCompressionType::Zstd:547Chdr.ch_type = ELF::ELFCOMPRESS_ZSTD;548break;549}550Chdr.ch_size = Sec.DecompressedSize;551Chdr.ch_addralign = Sec.DecompressedAlign;552memcpy(Buf, &Chdr, sizeof(Chdr));553Buf += sizeof(Chdr);554555std::copy(Sec.CompressedData.begin(), Sec.CompressedData.end(), Buf);556return Error::success();557}558559CompressedSection::CompressedSection(const SectionBase &Sec,560DebugCompressionType CompressionType,561bool Is64Bits)562: SectionBase(Sec), CompressionType(CompressionType),563DecompressedSize(Sec.OriginalData.size()), DecompressedAlign(Sec.Align) {564compression::compress(compression::Params(CompressionType), OriginalData,565CompressedData);566567Flags |= ELF::SHF_COMPRESSED;568OriginalFlags |= ELF::SHF_COMPRESSED;569size_t ChdrSize = Is64Bits ? sizeof(object::Elf_Chdr_Impl<object::ELF64LE>)570: sizeof(object::Elf_Chdr_Impl<object::ELF32LE>);571Size = ChdrSize + CompressedData.size();572Align = 8;573}574575CompressedSection::CompressedSection(ArrayRef<uint8_t> CompressedData,576uint32_t ChType, uint64_t DecompressedSize,577uint64_t DecompressedAlign)578: ChType(ChType), CompressionType(DebugCompressionType::None),579DecompressedSize(DecompressedSize), DecompressedAlign(DecompressedAlign) {580OriginalData = CompressedData;581}582583Error CompressedSection::accept(SectionVisitor &Visitor) const {584return Visitor.visit(*this);585}586587Error CompressedSection::accept(MutableSectionVisitor &Visitor) {588return Visitor.visit(*this);589}590591void StringTableSection::addString(StringRef Name) { StrTabBuilder.add(Name); }592593uint32_t StringTableSection::findIndex(StringRef Name) const {594return StrTabBuilder.getOffset(Name);595}596597void StringTableSection::prepareForLayout() {598StrTabBuilder.finalize();599Size = StrTabBuilder.getSize();600}601602Error SectionWriter::visit(const StringTableSection &Sec) {603Sec.StrTabBuilder.write(reinterpret_cast<uint8_t *>(Out.getBufferStart()) +604Sec.Offset);605return Error::success();606}607608Error StringTableSection::accept(SectionVisitor &Visitor) const {609return Visitor.visit(*this);610}611612Error StringTableSection::accept(MutableSectionVisitor &Visitor) {613return Visitor.visit(*this);614}615616template <class ELFT>617Error ELFSectionWriter<ELFT>::visit(const SectionIndexSection &Sec) {618uint8_t *Buf = reinterpret_cast<uint8_t *>(Out.getBufferStart()) + Sec.Offset;619llvm::copy(Sec.Indexes, reinterpret_cast<Elf_Word *>(Buf));620return Error::success();621}622623Error SectionIndexSection::initialize(SectionTableRef SecTable) {624Size = 0;625Expected<SymbolTableSection *> Sec =626SecTable.getSectionOfType<SymbolTableSection>(627Link,628"Link field value " + Twine(Link) + " in section " + Name +629" is invalid",630"Link field value " + Twine(Link) + " in section " + Name +631" is not a symbol table");632if (!Sec)633return Sec.takeError();634635setSymTab(*Sec);636Symbols->setShndxTable(this);637return Error::success();638}639640void SectionIndexSection::finalize() { Link = Symbols->Index; }641642Error SectionIndexSection::accept(SectionVisitor &Visitor) const {643return Visitor.visit(*this);644}645646Error SectionIndexSection::accept(MutableSectionVisitor &Visitor) {647return Visitor.visit(*this);648}649650static bool isValidReservedSectionIndex(uint16_t Index, uint16_t Machine) {651switch (Index) {652case SHN_ABS:653case SHN_COMMON:654return true;655}656657if (Machine == EM_AMDGPU) {658return Index == SHN_AMDGPU_LDS;659}660661if (Machine == EM_MIPS) {662switch (Index) {663case SHN_MIPS_ACOMMON:664case SHN_MIPS_SCOMMON:665case SHN_MIPS_SUNDEFINED:666return true;667}668}669670if (Machine == EM_HEXAGON) {671switch (Index) {672case SHN_HEXAGON_SCOMMON:673case SHN_HEXAGON_SCOMMON_1:674case SHN_HEXAGON_SCOMMON_2:675case SHN_HEXAGON_SCOMMON_4:676case SHN_HEXAGON_SCOMMON_8:677return true;678}679}680return false;681}682683// Large indexes force us to clarify exactly what this function should do. This684// function should return the value that will appear in st_shndx when written685// out.686uint16_t Symbol::getShndx() const {687if (DefinedIn != nullptr) {688if (DefinedIn->Index >= SHN_LORESERVE)689return SHN_XINDEX;690return DefinedIn->Index;691}692693if (ShndxType == SYMBOL_SIMPLE_INDEX) {694// This means that we don't have a defined section but we do need to695// output a legitimate section index.696return SHN_UNDEF;697}698699assert(ShndxType == SYMBOL_ABS || ShndxType == SYMBOL_COMMON ||700(ShndxType >= SYMBOL_LOPROC && ShndxType <= SYMBOL_HIPROC) ||701(ShndxType >= SYMBOL_LOOS && ShndxType <= SYMBOL_HIOS));702return static_cast<uint16_t>(ShndxType);703}704705bool Symbol::isCommon() const { return getShndx() == SHN_COMMON; }706707void SymbolTableSection::assignIndices() {708uint32_t Index = 0;709for (auto &Sym : Symbols) {710if (Sym->Index != Index)711IndicesChanged = true;712Sym->Index = Index++;713}714}715716void SymbolTableSection::addSymbol(Twine Name, uint8_t Bind, uint8_t Type,717SectionBase *DefinedIn, uint64_t Value,718uint8_t Visibility, uint16_t Shndx,719uint64_t SymbolSize) {720Symbol Sym;721Sym.Name = Name.str();722Sym.Binding = Bind;723Sym.Type = Type;724Sym.DefinedIn = DefinedIn;725if (DefinedIn != nullptr)726DefinedIn->HasSymbol = true;727if (DefinedIn == nullptr) {728if (Shndx >= SHN_LORESERVE)729Sym.ShndxType = static_cast<SymbolShndxType>(Shndx);730else731Sym.ShndxType = SYMBOL_SIMPLE_INDEX;732}733Sym.Value = Value;734Sym.Visibility = Visibility;735Sym.Size = SymbolSize;736Sym.Index = Symbols.size();737Symbols.emplace_back(std::make_unique<Symbol>(Sym));738Size += this->EntrySize;739}740741Error SymbolTableSection::removeSectionReferences(742bool AllowBrokenLinks, function_ref<bool(const SectionBase *)> ToRemove) {743if (ToRemove(SectionIndexTable))744SectionIndexTable = nullptr;745if (ToRemove(SymbolNames)) {746if (!AllowBrokenLinks)747return createStringError(748llvm::errc::invalid_argument,749"string table '%s' cannot be removed because it is "750"referenced by the symbol table '%s'",751SymbolNames->Name.data(), this->Name.data());752SymbolNames = nullptr;753}754return removeSymbols(755[ToRemove](const Symbol &Sym) { return ToRemove(Sym.DefinedIn); });756}757758void SymbolTableSection::updateSymbols(function_ref<void(Symbol &)> Callable) {759for (SymPtr &Sym : llvm::drop_begin(Symbols))760Callable(*Sym);761std::stable_partition(762std::begin(Symbols), std::end(Symbols),763[](const SymPtr &Sym) { return Sym->Binding == STB_LOCAL; });764assignIndices();765}766767Error SymbolTableSection::removeSymbols(768function_ref<bool(const Symbol &)> ToRemove) {769Symbols.erase(770std::remove_if(std::begin(Symbols) + 1, std::end(Symbols),771[ToRemove](const SymPtr &Sym) { return ToRemove(*Sym); }),772std::end(Symbols));773auto PrevSize = Size;774Size = Symbols.size() * EntrySize;775if (Size < PrevSize)776IndicesChanged = true;777assignIndices();778return Error::success();779}780781void SymbolTableSection::replaceSectionReferences(782const DenseMap<SectionBase *, SectionBase *> &FromTo) {783for (std::unique_ptr<Symbol> &Sym : Symbols)784if (SectionBase *To = FromTo.lookup(Sym->DefinedIn))785Sym->DefinedIn = To;786}787788Error SymbolTableSection::initialize(SectionTableRef SecTable) {789Size = 0;790Expected<StringTableSection *> Sec =791SecTable.getSectionOfType<StringTableSection>(792Link,793"Symbol table has link index of " + Twine(Link) +794" which is not a valid index",795"Symbol table has link index of " + Twine(Link) +796" which is not a string table");797if (!Sec)798return Sec.takeError();799800setStrTab(*Sec);801return Error::success();802}803804void SymbolTableSection::finalize() {805uint32_t MaxLocalIndex = 0;806for (std::unique_ptr<Symbol> &Sym : Symbols) {807Sym->NameIndex =808SymbolNames == nullptr ? 0 : SymbolNames->findIndex(Sym->Name);809if (Sym->Binding == STB_LOCAL)810MaxLocalIndex = std::max(MaxLocalIndex, Sym->Index);811}812// Now we need to set the Link and Info fields.813Link = SymbolNames == nullptr ? 0 : SymbolNames->Index;814Info = MaxLocalIndex + 1;815}816817void SymbolTableSection::prepareForLayout() {818// Reserve proper amount of space in section index table, so we can819// layout sections correctly. We will fill the table with correct820// indexes later in fillShdnxTable.821if (SectionIndexTable)822SectionIndexTable->reserve(Symbols.size());823824// Add all of our strings to SymbolNames so that SymbolNames has the right825// size before layout is decided.826// If the symbol names section has been removed, don't try to add strings to827// the table.828if (SymbolNames != nullptr)829for (std::unique_ptr<Symbol> &Sym : Symbols)830SymbolNames->addString(Sym->Name);831}832833void SymbolTableSection::fillShndxTable() {834if (SectionIndexTable == nullptr)835return;836// Fill section index table with real section indexes. This function must837// be called after assignOffsets.838for (const std::unique_ptr<Symbol> &Sym : Symbols) {839if (Sym->DefinedIn != nullptr && Sym->DefinedIn->Index >= SHN_LORESERVE)840SectionIndexTable->addIndex(Sym->DefinedIn->Index);841else842SectionIndexTable->addIndex(SHN_UNDEF);843}844}845846Expected<const Symbol *>847SymbolTableSection::getSymbolByIndex(uint32_t Index) const {848if (Symbols.size() <= Index)849return createStringError(errc::invalid_argument,850"invalid symbol index: " + Twine(Index));851return Symbols[Index].get();852}853854Expected<Symbol *> SymbolTableSection::getSymbolByIndex(uint32_t Index) {855Expected<const Symbol *> Sym =856static_cast<const SymbolTableSection *>(this)->getSymbolByIndex(Index);857if (!Sym)858return Sym.takeError();859860return const_cast<Symbol *>(*Sym);861}862863template <class ELFT>864Error ELFSectionWriter<ELFT>::visit(const SymbolTableSection &Sec) {865Elf_Sym *Sym = reinterpret_cast<Elf_Sym *>(Out.getBufferStart() + Sec.Offset);866// Loop though symbols setting each entry of the symbol table.867for (const std::unique_ptr<Symbol> &Symbol : Sec.Symbols) {868Sym->st_name = Symbol->NameIndex;869Sym->st_value = Symbol->Value;870Sym->st_size = Symbol->Size;871Sym->st_other = Symbol->Visibility;872Sym->setBinding(Symbol->Binding);873Sym->setType(Symbol->Type);874Sym->st_shndx = Symbol->getShndx();875++Sym;876}877return Error::success();878}879880Error SymbolTableSection::accept(SectionVisitor &Visitor) const {881return Visitor.visit(*this);882}883884Error SymbolTableSection::accept(MutableSectionVisitor &Visitor) {885return Visitor.visit(*this);886}887888StringRef RelocationSectionBase::getNamePrefix() const {889switch (Type) {890case SHT_REL:891return ".rel";892case SHT_RELA:893return ".rela";894case SHT_CREL:895return ".crel";896default:897llvm_unreachable("not a relocation section");898}899}900901Error RelocationSection::removeSectionReferences(902bool AllowBrokenLinks, function_ref<bool(const SectionBase *)> ToRemove) {903if (ToRemove(Symbols)) {904if (!AllowBrokenLinks)905return createStringError(906llvm::errc::invalid_argument,907"symbol table '%s' cannot be removed because it is "908"referenced by the relocation section '%s'",909Symbols->Name.data(), this->Name.data());910Symbols = nullptr;911}912913for (const Relocation &R : Relocations) {914if (!R.RelocSymbol || !R.RelocSymbol->DefinedIn ||915!ToRemove(R.RelocSymbol->DefinedIn))916continue;917return createStringError(llvm::errc::invalid_argument,918"section '%s' cannot be removed: (%s+0x%" PRIx64919") has relocation against symbol '%s'",920R.RelocSymbol->DefinedIn->Name.data(),921SecToApplyRel->Name.data(), R.Offset,922R.RelocSymbol->Name.c_str());923}924925return Error::success();926}927928template <class SymTabType>929Error RelocSectionWithSymtabBase<SymTabType>::initialize(930SectionTableRef SecTable) {931if (Link != SHN_UNDEF) {932Expected<SymTabType *> Sec = SecTable.getSectionOfType<SymTabType>(933Link,934"Link field value " + Twine(Link) + " in section " + Name +935" is invalid",936"Link field value " + Twine(Link) + " in section " + Name +937" is not a symbol table");938if (!Sec)939return Sec.takeError();940941setSymTab(*Sec);942}943944if (Info != SHN_UNDEF) {945Expected<SectionBase *> Sec =946SecTable.getSection(Info, "Info field value " + Twine(Info) +947" in section " + Name + " is invalid");948if (!Sec)949return Sec.takeError();950951setSection(*Sec);952} else953setSection(nullptr);954955return Error::success();956}957958template <class SymTabType>959void RelocSectionWithSymtabBase<SymTabType>::finalize() {960this->Link = Symbols ? Symbols->Index : 0;961962if (SecToApplyRel != nullptr)963this->Info = SecToApplyRel->Index;964}965966template <class ELFT>967static void setAddend(Elf_Rel_Impl<ELFT, false> &, uint64_t) {}968969template <class ELFT>970static void setAddend(Elf_Rel_Impl<ELFT, true> &Rela, uint64_t Addend) {971Rela.r_addend = Addend;972}973974template <class RelRange, class T>975static void writeRel(const RelRange &Relocations, T *Buf, bool IsMips64EL) {976for (const auto &Reloc : Relocations) {977Buf->r_offset = Reloc.Offset;978setAddend(*Buf, Reloc.Addend);979Buf->setSymbolAndType(Reloc.RelocSymbol ? Reloc.RelocSymbol->Index : 0,980Reloc.Type, IsMips64EL);981++Buf;982}983}984985template <class ELFT>986Error ELFSectionWriter<ELFT>::visit(const RelocationSection &Sec) {987uint8_t *Buf = reinterpret_cast<uint8_t *>(Out.getBufferStart()) + Sec.Offset;988if (Sec.Type == SHT_CREL) {989auto Content = encodeCrel<ELFT::Is64Bits>(Sec.Relocations);990memcpy(Buf, Content.data(), Content.size());991} else if (Sec.Type == SHT_REL) {992writeRel(Sec.Relocations, reinterpret_cast<Elf_Rel *>(Buf),993Sec.getObject().IsMips64EL);994} else {995writeRel(Sec.Relocations, reinterpret_cast<Elf_Rela *>(Buf),996Sec.getObject().IsMips64EL);997}998return Error::success();999}10001001Error RelocationSection::accept(SectionVisitor &Visitor) const {1002return Visitor.visit(*this);1003}10041005Error RelocationSection::accept(MutableSectionVisitor &Visitor) {1006return Visitor.visit(*this);1007}10081009Error RelocationSection::removeSymbols(1010function_ref<bool(const Symbol &)> ToRemove) {1011for (const Relocation &Reloc : Relocations)1012if (Reloc.RelocSymbol && ToRemove(*Reloc.RelocSymbol))1013return createStringError(1014llvm::errc::invalid_argument,1015"not stripping symbol '%s' because it is named in a relocation",1016Reloc.RelocSymbol->Name.data());1017return Error::success();1018}10191020void RelocationSection::markSymbols() {1021for (const Relocation &Reloc : Relocations)1022if (Reloc.RelocSymbol)1023Reloc.RelocSymbol->Referenced = true;1024}10251026void RelocationSection::replaceSectionReferences(1027const DenseMap<SectionBase *, SectionBase *> &FromTo) {1028// Update the target section if it was replaced.1029if (SectionBase *To = FromTo.lookup(SecToApplyRel))1030SecToApplyRel = To;1031}10321033Error SectionWriter::visit(const DynamicRelocationSection &Sec) {1034llvm::copy(Sec.Contents, Out.getBufferStart() + Sec.Offset);1035return Error::success();1036}10371038Error DynamicRelocationSection::accept(SectionVisitor &Visitor) const {1039return Visitor.visit(*this);1040}10411042Error DynamicRelocationSection::accept(MutableSectionVisitor &Visitor) {1043return Visitor.visit(*this);1044}10451046Error DynamicRelocationSection::removeSectionReferences(1047bool AllowBrokenLinks, function_ref<bool(const SectionBase *)> ToRemove) {1048if (ToRemove(Symbols)) {1049if (!AllowBrokenLinks)1050return createStringError(1051llvm::errc::invalid_argument,1052"symbol table '%s' cannot be removed because it is "1053"referenced by the relocation section '%s'",1054Symbols->Name.data(), this->Name.data());1055Symbols = nullptr;1056}10571058// SecToApplyRel contains a section referenced by sh_info field. It keeps1059// a section to which the relocation section applies. When we remove any1060// sections we also remove their relocation sections. Since we do that much1061// earlier, this assert should never be triggered.1062assert(!SecToApplyRel || !ToRemove(SecToApplyRel));1063return Error::success();1064}10651066Error Section::removeSectionReferences(1067bool AllowBrokenDependency,1068function_ref<bool(const SectionBase *)> ToRemove) {1069if (ToRemove(LinkSection)) {1070if (!AllowBrokenDependency)1071return createStringError(llvm::errc::invalid_argument,1072"section '%s' cannot be removed because it is "1073"referenced by the section '%s'",1074LinkSection->Name.data(), this->Name.data());1075LinkSection = nullptr;1076}1077return Error::success();1078}10791080void GroupSection::finalize() {1081this->Info = Sym ? Sym->Index : 0;1082this->Link = SymTab ? SymTab->Index : 0;1083// Linker deduplication for GRP_COMDAT is based on Sym->Name. The local/global1084// status is not part of the equation. If Sym is localized, the intention is1085// likely to make the group fully localized. Drop GRP_COMDAT to suppress1086// deduplication. See https://groups.google.com/g/generic-abi/c/2X6mR-s2zoc1087if ((FlagWord & GRP_COMDAT) && Sym && Sym->Binding == STB_LOCAL)1088this->FlagWord &= ~GRP_COMDAT;1089}10901091Error GroupSection::removeSectionReferences(1092bool AllowBrokenLinks, function_ref<bool(const SectionBase *)> ToRemove) {1093if (ToRemove(SymTab)) {1094if (!AllowBrokenLinks)1095return createStringError(1096llvm::errc::invalid_argument,1097"section '.symtab' cannot be removed because it is "1098"referenced by the group section '%s'",1099this->Name.data());1100SymTab = nullptr;1101Sym = nullptr;1102}1103llvm::erase_if(GroupMembers, ToRemove);1104return Error::success();1105}11061107Error GroupSection::removeSymbols(function_ref<bool(const Symbol &)> ToRemove) {1108if (ToRemove(*Sym))1109return createStringError(llvm::errc::invalid_argument,1110"symbol '%s' cannot be removed because it is "1111"referenced by the section '%s[%d]'",1112Sym->Name.data(), this->Name.data(), this->Index);1113return Error::success();1114}11151116void GroupSection::markSymbols() {1117if (Sym)1118Sym->Referenced = true;1119}11201121void GroupSection::replaceSectionReferences(1122const DenseMap<SectionBase *, SectionBase *> &FromTo) {1123for (SectionBase *&Sec : GroupMembers)1124if (SectionBase *To = FromTo.lookup(Sec))1125Sec = To;1126}11271128void GroupSection::onRemove() {1129// As the header section of the group is removed, drop the Group flag in its1130// former members.1131for (SectionBase *Sec : GroupMembers)1132Sec->Flags &= ~SHF_GROUP;1133}11341135Error Section::initialize(SectionTableRef SecTable) {1136if (Link == ELF::SHN_UNDEF)1137return Error::success();11381139Expected<SectionBase *> Sec =1140SecTable.getSection(Link, "Link field value " + Twine(Link) +1141" in section " + Name + " is invalid");1142if (!Sec)1143return Sec.takeError();11441145LinkSection = *Sec;11461147if (LinkSection->Type == ELF::SHT_SYMTAB) {1148HasSymTabLink = true;1149LinkSection = nullptr;1150}11511152return Error::success();1153}11541155void Section::finalize() { this->Link = LinkSection ? LinkSection->Index : 0; }11561157void GnuDebugLinkSection::init(StringRef File) {1158FileName = sys::path::filename(File);1159// The format for the .gnu_debuglink starts with the file name and is1160// followed by a null terminator and then the CRC32 of the file. The CRC321161// should be 4 byte aligned. So we add the FileName size, a 1 for the null1162// byte, and then finally push the size to alignment and add 4.1163Size = alignTo(FileName.size() + 1, 4) + 4;1164// The CRC32 will only be aligned if we align the whole section.1165Align = 4;1166Type = OriginalType = ELF::SHT_PROGBITS;1167Name = ".gnu_debuglink";1168// For sections not found in segments, OriginalOffset is only used to1169// establish the order that sections should go in. By using the maximum1170// possible offset we cause this section to wind up at the end.1171OriginalOffset = std::numeric_limits<uint64_t>::max();1172}11731174GnuDebugLinkSection::GnuDebugLinkSection(StringRef File,1175uint32_t PrecomputedCRC)1176: FileName(File), CRC32(PrecomputedCRC) {1177init(File);1178}11791180template <class ELFT>1181Error ELFSectionWriter<ELFT>::visit(const GnuDebugLinkSection &Sec) {1182unsigned char *Buf =1183reinterpret_cast<uint8_t *>(Out.getBufferStart()) + Sec.Offset;1184Elf_Word *CRC =1185reinterpret_cast<Elf_Word *>(Buf + Sec.Size - sizeof(Elf_Word));1186*CRC = Sec.CRC32;1187llvm::copy(Sec.FileName, Buf);1188return Error::success();1189}11901191Error GnuDebugLinkSection::accept(SectionVisitor &Visitor) const {1192return Visitor.visit(*this);1193}11941195Error GnuDebugLinkSection::accept(MutableSectionVisitor &Visitor) {1196return Visitor.visit(*this);1197}11981199template <class ELFT>1200Error ELFSectionWriter<ELFT>::visit(const GroupSection &Sec) {1201ELF::Elf32_Word *Buf =1202reinterpret_cast<ELF::Elf32_Word *>(Out.getBufferStart() + Sec.Offset);1203endian::write32<ELFT::Endianness>(Buf++, Sec.FlagWord);1204for (SectionBase *S : Sec.GroupMembers)1205endian::write32<ELFT::Endianness>(Buf++, S->Index);1206return Error::success();1207}12081209Error GroupSection::accept(SectionVisitor &Visitor) const {1210return Visitor.visit(*this);1211}12121213Error GroupSection::accept(MutableSectionVisitor &Visitor) {1214return Visitor.visit(*this);1215}12161217// Returns true IFF a section is wholly inside the range of a segment1218static bool sectionWithinSegment(const SectionBase &Sec, const Segment &Seg) {1219// If a section is empty it should be treated like it has a size of 1. This is1220// to clarify the case when an empty section lies on a boundary between two1221// segments and ensures that the section "belongs" to the second segment and1222// not the first.1223uint64_t SecSize = Sec.Size ? Sec.Size : 1;12241225// Ignore just added sections.1226if (Sec.OriginalOffset == std::numeric_limits<uint64_t>::max())1227return false;12281229if (Sec.Type == SHT_NOBITS) {1230if (!(Sec.Flags & SHF_ALLOC))1231return false;12321233bool SectionIsTLS = Sec.Flags & SHF_TLS;1234bool SegmentIsTLS = Seg.Type == PT_TLS;1235if (SectionIsTLS != SegmentIsTLS)1236return false;12371238return Seg.VAddr <= Sec.Addr &&1239Seg.VAddr + Seg.MemSize >= Sec.Addr + SecSize;1240}12411242return Seg.Offset <= Sec.OriginalOffset &&1243Seg.Offset + Seg.FileSize >= Sec.OriginalOffset + SecSize;1244}12451246// Returns true IFF a segment's original offset is inside of another segment's1247// range.1248static bool segmentOverlapsSegment(const Segment &Child,1249const Segment &Parent) {12501251return Parent.OriginalOffset <= Child.OriginalOffset &&1252Parent.OriginalOffset + Parent.FileSize > Child.OriginalOffset;1253}12541255static bool compareSegmentsByOffset(const Segment *A, const Segment *B) {1256// Any segment without a parent segment should come before a segment1257// that has a parent segment.1258if (A->OriginalOffset < B->OriginalOffset)1259return true;1260if (A->OriginalOffset > B->OriginalOffset)1261return false;1262// If alignments are different, the one with a smaller alignment cannot be the1263// parent; otherwise, layoutSegments will not respect the larger alignment1264// requirement. This rule ensures that PT_LOAD/PT_INTERP/PT_GNU_RELRO/PT_TLS1265// segments at the same offset will be aligned correctly.1266if (A->Align != B->Align)1267return A->Align > B->Align;1268return A->Index < B->Index;1269}12701271void BasicELFBuilder::initFileHeader() {1272Obj->Flags = 0x0;1273Obj->Type = ET_REL;1274Obj->OSABI = ELFOSABI_NONE;1275Obj->ABIVersion = 0;1276Obj->Entry = 0x0;1277Obj->Machine = EM_NONE;1278Obj->Version = 1;1279}12801281void BasicELFBuilder::initHeaderSegment() { Obj->ElfHdrSegment.Index = 0; }12821283StringTableSection *BasicELFBuilder::addStrTab() {1284auto &StrTab = Obj->addSection<StringTableSection>();1285StrTab.Name = ".strtab";12861287Obj->SectionNames = &StrTab;1288return &StrTab;1289}12901291SymbolTableSection *BasicELFBuilder::addSymTab(StringTableSection *StrTab) {1292auto &SymTab = Obj->addSection<SymbolTableSection>();12931294SymTab.Name = ".symtab";1295SymTab.Link = StrTab->Index;12961297// The symbol table always needs a null symbol1298SymTab.addSymbol("", 0, 0, nullptr, 0, 0, 0, 0);12991300Obj->SymbolTable = &SymTab;1301return &SymTab;1302}13031304Error BasicELFBuilder::initSections() {1305for (SectionBase &Sec : Obj->sections())1306if (Error Err = Sec.initialize(Obj->sections()))1307return Err;13081309return Error::success();1310}13111312void BinaryELFBuilder::addData(SymbolTableSection *SymTab) {1313auto Data = ArrayRef<uint8_t>(1314reinterpret_cast<const uint8_t *>(MemBuf->getBufferStart()),1315MemBuf->getBufferSize());1316auto &DataSection = Obj->addSection<Section>(Data);1317DataSection.Name = ".data";1318DataSection.Type = ELF::SHT_PROGBITS;1319DataSection.Size = Data.size();1320DataSection.Flags = ELF::SHF_ALLOC | ELF::SHF_WRITE;13211322std::string SanitizedFilename = MemBuf->getBufferIdentifier().str();1323std::replace_if(1324std::begin(SanitizedFilename), std::end(SanitizedFilename),1325[](char C) { return !isAlnum(C); }, '_');1326Twine Prefix = Twine("_binary_") + SanitizedFilename;13271328SymTab->addSymbol(Prefix + "_start", STB_GLOBAL, STT_NOTYPE, &DataSection,1329/*Value=*/0, NewSymbolVisibility, 0, 0);1330SymTab->addSymbol(Prefix + "_end", STB_GLOBAL, STT_NOTYPE, &DataSection,1331/*Value=*/DataSection.Size, NewSymbolVisibility, 0, 0);1332SymTab->addSymbol(Prefix + "_size", STB_GLOBAL, STT_NOTYPE, nullptr,1333/*Value=*/DataSection.Size, NewSymbolVisibility, SHN_ABS,13340);1335}13361337Expected<std::unique_ptr<Object>> BinaryELFBuilder::build() {1338initFileHeader();1339initHeaderSegment();13401341SymbolTableSection *SymTab = addSymTab(addStrTab());1342if (Error Err = initSections())1343return std::move(Err);1344addData(SymTab);13451346return std::move(Obj);1347}13481349// Adds sections from IHEX data file. Data should have been1350// fully validated by this time.1351void IHexELFBuilder::addDataSections() {1352OwnedDataSection *Section = nullptr;1353uint64_t SegmentAddr = 0, BaseAddr = 0;1354uint32_t SecNo = 1;13551356for (const IHexRecord &R : Records) {1357uint64_t RecAddr;1358switch (R.Type) {1359case IHexRecord::Data:1360// Ignore empty data records1361if (R.HexData.empty())1362continue;1363RecAddr = R.Addr + SegmentAddr + BaseAddr;1364if (!Section || Section->Addr + Section->Size != RecAddr) {1365// OriginalOffset field is only used to sort sections before layout, so1366// instead of keeping track of real offsets in IHEX file, and as1367// layoutSections() and layoutSectionsForOnlyKeepDebug() use1368// llvm::stable_sort(), we can just set it to a constant (zero).1369Section = &Obj->addSection<OwnedDataSection>(1370".sec" + std::to_string(SecNo), RecAddr,1371ELF::SHF_ALLOC | ELF::SHF_WRITE, 0);1372SecNo++;1373}1374Section->appendHexData(R.HexData);1375break;1376case IHexRecord::EndOfFile:1377break;1378case IHexRecord::SegmentAddr:1379// 20-bit segment address.1380SegmentAddr = checkedGetHex<uint16_t>(R.HexData) << 4;1381break;1382case IHexRecord::StartAddr80x86:1383case IHexRecord::StartAddr:1384Obj->Entry = checkedGetHex<uint32_t>(R.HexData);1385assert(Obj->Entry <= 0xFFFFFU);1386break;1387case IHexRecord::ExtendedAddr:1388// 16-31 bits of linear base address1389BaseAddr = checkedGetHex<uint16_t>(R.HexData) << 16;1390break;1391default:1392llvm_unreachable("unknown record type");1393}1394}1395}13961397Expected<std::unique_ptr<Object>> IHexELFBuilder::build() {1398initFileHeader();1399initHeaderSegment();1400StringTableSection *StrTab = addStrTab();1401addSymTab(StrTab);1402if (Error Err = initSections())1403return std::move(Err);1404addDataSections();14051406return std::move(Obj);1407}14081409template <class ELFT>1410ELFBuilder<ELFT>::ELFBuilder(const ELFObjectFile<ELFT> &ElfObj, Object &Obj,1411std::optional<StringRef> ExtractPartition)1412: ElfFile(ElfObj.getELFFile()), Obj(Obj),1413ExtractPartition(ExtractPartition) {1414Obj.IsMips64EL = ElfFile.isMips64EL();1415}14161417template <class ELFT> void ELFBuilder<ELFT>::setParentSegment(Segment &Child) {1418for (Segment &Parent : Obj.segments()) {1419// Every segment will overlap with itself but we don't want a segment to1420// be its own parent so we avoid that situation.1421if (&Child != &Parent && segmentOverlapsSegment(Child, Parent)) {1422// We want a canonical "most parental" segment but this requires1423// inspecting the ParentSegment.1424if (compareSegmentsByOffset(&Parent, &Child))1425if (Child.ParentSegment == nullptr ||1426compareSegmentsByOffset(&Parent, Child.ParentSegment)) {1427Child.ParentSegment = &Parent;1428}1429}1430}1431}14321433template <class ELFT> Error ELFBuilder<ELFT>::findEhdrOffset() {1434if (!ExtractPartition)1435return Error::success();14361437for (const SectionBase &Sec : Obj.sections()) {1438if (Sec.Type == SHT_LLVM_PART_EHDR && Sec.Name == *ExtractPartition) {1439EhdrOffset = Sec.Offset;1440return Error::success();1441}1442}1443return createStringError(errc::invalid_argument,1444"could not find partition named '" +1445*ExtractPartition + "'");1446}14471448template <class ELFT>1449Error ELFBuilder<ELFT>::readProgramHeaders(const ELFFile<ELFT> &HeadersFile) {1450uint32_t Index = 0;14511452Expected<typename ELFFile<ELFT>::Elf_Phdr_Range> Headers =1453HeadersFile.program_headers();1454if (!Headers)1455return Headers.takeError();14561457for (const typename ELFFile<ELFT>::Elf_Phdr &Phdr : *Headers) {1458if (Phdr.p_offset + Phdr.p_filesz > HeadersFile.getBufSize())1459return createStringError(1460errc::invalid_argument,1461"program header with offset 0x" + Twine::utohexstr(Phdr.p_offset) +1462" and file size 0x" + Twine::utohexstr(Phdr.p_filesz) +1463" goes past the end of the file");14641465ArrayRef<uint8_t> Data{HeadersFile.base() + Phdr.p_offset,1466(size_t)Phdr.p_filesz};1467Segment &Seg = Obj.addSegment(Data);1468Seg.Type = Phdr.p_type;1469Seg.Flags = Phdr.p_flags;1470Seg.OriginalOffset = Phdr.p_offset + EhdrOffset;1471Seg.Offset = Phdr.p_offset + EhdrOffset;1472Seg.VAddr = Phdr.p_vaddr;1473Seg.PAddr = Phdr.p_paddr;1474Seg.FileSize = Phdr.p_filesz;1475Seg.MemSize = Phdr.p_memsz;1476Seg.Align = Phdr.p_align;1477Seg.Index = Index++;1478for (SectionBase &Sec : Obj.sections())1479if (sectionWithinSegment(Sec, Seg)) {1480Seg.addSection(&Sec);1481if (!Sec.ParentSegment || Sec.ParentSegment->Offset > Seg.Offset)1482Sec.ParentSegment = &Seg;1483}1484}14851486auto &ElfHdr = Obj.ElfHdrSegment;1487ElfHdr.Index = Index++;1488ElfHdr.OriginalOffset = ElfHdr.Offset = EhdrOffset;14891490const typename ELFT::Ehdr &Ehdr = HeadersFile.getHeader();1491auto &PrHdr = Obj.ProgramHdrSegment;1492PrHdr.Type = PT_PHDR;1493PrHdr.Flags = 0;1494// The spec requires us to have p_vaddr % p_align == p_offset % p_align.1495// Whereas this works automatically for ElfHdr, here OriginalOffset is1496// always non-zero and to ensure the equation we assign the same value to1497// VAddr as well.1498PrHdr.OriginalOffset = PrHdr.Offset = PrHdr.VAddr = EhdrOffset + Ehdr.e_phoff;1499PrHdr.PAddr = 0;1500PrHdr.FileSize = PrHdr.MemSize = Ehdr.e_phentsize * Ehdr.e_phnum;1501// The spec requires us to naturally align all the fields.1502PrHdr.Align = sizeof(Elf_Addr);1503PrHdr.Index = Index++;15041505// Now we do an O(n^2) loop through the segments in order to match up1506// segments.1507for (Segment &Child : Obj.segments())1508setParentSegment(Child);1509setParentSegment(ElfHdr);1510setParentSegment(PrHdr);15111512return Error::success();1513}15141515template <class ELFT>1516Error ELFBuilder<ELFT>::initGroupSection(GroupSection *GroupSec) {1517if (GroupSec->Align % sizeof(ELF::Elf32_Word) != 0)1518return createStringError(errc::invalid_argument,1519"invalid alignment " + Twine(GroupSec->Align) +1520" of group section '" + GroupSec->Name + "'");1521SectionTableRef SecTable = Obj.sections();1522if (GroupSec->Link != SHN_UNDEF) {1523auto SymTab = SecTable.template getSectionOfType<SymbolTableSection>(1524GroupSec->Link,1525"link field value '" + Twine(GroupSec->Link) + "' in section '" +1526GroupSec->Name + "' is invalid",1527"link field value '" + Twine(GroupSec->Link) + "' in section '" +1528GroupSec->Name + "' is not a symbol table");1529if (!SymTab)1530return SymTab.takeError();15311532Expected<Symbol *> Sym = (*SymTab)->getSymbolByIndex(GroupSec->Info);1533if (!Sym)1534return createStringError(errc::invalid_argument,1535"info field value '" + Twine(GroupSec->Info) +1536"' in section '" + GroupSec->Name +1537"' is not a valid symbol index");1538GroupSec->setSymTab(*SymTab);1539GroupSec->setSymbol(*Sym);1540}1541if (GroupSec->Contents.size() % sizeof(ELF::Elf32_Word) ||1542GroupSec->Contents.empty())1543return createStringError(errc::invalid_argument,1544"the content of the section " + GroupSec->Name +1545" is malformed");1546const ELF::Elf32_Word *Word =1547reinterpret_cast<const ELF::Elf32_Word *>(GroupSec->Contents.data());1548const ELF::Elf32_Word *End =1549Word + GroupSec->Contents.size() / sizeof(ELF::Elf32_Word);1550GroupSec->setFlagWord(endian::read32<ELFT::Endianness>(Word++));1551for (; Word != End; ++Word) {1552uint32_t Index = support::endian::read32<ELFT::Endianness>(Word);1553Expected<SectionBase *> Sec = SecTable.getSection(1554Index, "group member index " + Twine(Index) + " in section '" +1555GroupSec->Name + "' is invalid");1556if (!Sec)1557return Sec.takeError();15581559GroupSec->addMember(*Sec);1560}15611562return Error::success();1563}15641565template <class ELFT>1566Error ELFBuilder<ELFT>::initSymbolTable(SymbolTableSection *SymTab) {1567Expected<const Elf_Shdr *> Shdr = ElfFile.getSection(SymTab->Index);1568if (!Shdr)1569return Shdr.takeError();15701571Expected<StringRef> StrTabData = ElfFile.getStringTableForSymtab(**Shdr);1572if (!StrTabData)1573return StrTabData.takeError();15741575ArrayRef<Elf_Word> ShndxData;15761577Expected<typename ELFFile<ELFT>::Elf_Sym_Range> Symbols =1578ElfFile.symbols(*Shdr);1579if (!Symbols)1580return Symbols.takeError();15811582for (const typename ELFFile<ELFT>::Elf_Sym &Sym : *Symbols) {1583SectionBase *DefSection = nullptr;15841585Expected<StringRef> Name = Sym.getName(*StrTabData);1586if (!Name)1587return Name.takeError();15881589if (Sym.st_shndx == SHN_XINDEX) {1590if (SymTab->getShndxTable() == nullptr)1591return createStringError(errc::invalid_argument,1592"symbol '" + *Name +1593"' has index SHN_XINDEX but no "1594"SHT_SYMTAB_SHNDX section exists");1595if (ShndxData.data() == nullptr) {1596Expected<const Elf_Shdr *> ShndxSec =1597ElfFile.getSection(SymTab->getShndxTable()->Index);1598if (!ShndxSec)1599return ShndxSec.takeError();16001601Expected<ArrayRef<Elf_Word>> Data =1602ElfFile.template getSectionContentsAsArray<Elf_Word>(**ShndxSec);1603if (!Data)1604return Data.takeError();16051606ShndxData = *Data;1607if (ShndxData.size() != Symbols->size())1608return createStringError(1609errc::invalid_argument,1610"symbol section index table does not have the same number of "1611"entries as the symbol table");1612}1613Elf_Word Index = ShndxData[&Sym - Symbols->begin()];1614Expected<SectionBase *> Sec = Obj.sections().getSection(1615Index,1616"symbol '" + *Name + "' has invalid section index " + Twine(Index));1617if (!Sec)1618return Sec.takeError();16191620DefSection = *Sec;1621} else if (Sym.st_shndx >= SHN_LORESERVE) {1622if (!isValidReservedSectionIndex(Sym.st_shndx, Obj.Machine)) {1623return createStringError(1624errc::invalid_argument,1625"symbol '" + *Name +1626"' has unsupported value greater than or equal "1627"to SHN_LORESERVE: " +1628Twine(Sym.st_shndx));1629}1630} else if (Sym.st_shndx != SHN_UNDEF) {1631Expected<SectionBase *> Sec = Obj.sections().getSection(1632Sym.st_shndx, "symbol '" + *Name +1633"' is defined has invalid section index " +1634Twine(Sym.st_shndx));1635if (!Sec)1636return Sec.takeError();16371638DefSection = *Sec;1639}16401641SymTab->addSymbol(*Name, Sym.getBinding(), Sym.getType(), DefSection,1642Sym.getValue(), Sym.st_other, Sym.st_shndx, Sym.st_size);1643}16441645return Error::success();1646}16471648template <class ELFT>1649static void getAddend(uint64_t &, const Elf_Rel_Impl<ELFT, false> &) {}16501651template <class ELFT>1652static void getAddend(uint64_t &ToSet, const Elf_Rel_Impl<ELFT, true> &Rela) {1653ToSet = Rela.r_addend;1654}16551656template <class T>1657static Error initRelocations(RelocationSection *Relocs, T RelRange) {1658for (const auto &Rel : RelRange) {1659Relocation ToAdd;1660ToAdd.Offset = Rel.r_offset;1661getAddend(ToAdd.Addend, Rel);1662ToAdd.Type = Rel.getType(Relocs->getObject().IsMips64EL);16631664if (uint32_t Sym = Rel.getSymbol(Relocs->getObject().IsMips64EL)) {1665if (!Relocs->getObject().SymbolTable)1666return createStringError(1667errc::invalid_argument,1668"'" + Relocs->Name + "': relocation references symbol with index " +1669Twine(Sym) + ", but there is no symbol table");1670Expected<Symbol *> SymByIndex =1671Relocs->getObject().SymbolTable->getSymbolByIndex(Sym);1672if (!SymByIndex)1673return SymByIndex.takeError();16741675ToAdd.RelocSymbol = *SymByIndex;1676}16771678Relocs->addRelocation(ToAdd);1679}16801681return Error::success();1682}16831684Expected<SectionBase *> SectionTableRef::getSection(uint32_t Index,1685Twine ErrMsg) {1686if (Index == SHN_UNDEF || Index > Sections.size())1687return createStringError(errc::invalid_argument, ErrMsg);1688return Sections[Index - 1].get();1689}16901691template <class T>1692Expected<T *> SectionTableRef::getSectionOfType(uint32_t Index,1693Twine IndexErrMsg,1694Twine TypeErrMsg) {1695Expected<SectionBase *> BaseSec = getSection(Index, IndexErrMsg);1696if (!BaseSec)1697return BaseSec.takeError();16981699if (T *Sec = dyn_cast<T>(*BaseSec))1700return Sec;17011702return createStringError(errc::invalid_argument, TypeErrMsg);1703}17041705template <class ELFT>1706Expected<SectionBase &> ELFBuilder<ELFT>::makeSection(const Elf_Shdr &Shdr) {1707switch (Shdr.sh_type) {1708case SHT_REL:1709case SHT_RELA:1710case SHT_CREL:1711if (Shdr.sh_flags & SHF_ALLOC) {1712if (Expected<ArrayRef<uint8_t>> Data = ElfFile.getSectionContents(Shdr))1713return Obj.addSection<DynamicRelocationSection>(*Data);1714else1715return Data.takeError();1716}1717return Obj.addSection<RelocationSection>(Obj);1718case SHT_STRTAB:1719// If a string table is allocated we don't want to mess with it. That would1720// mean altering the memory image. There are no special link types or1721// anything so we can just use a Section.1722if (Shdr.sh_flags & SHF_ALLOC) {1723if (Expected<ArrayRef<uint8_t>> Data = ElfFile.getSectionContents(Shdr))1724return Obj.addSection<Section>(*Data);1725else1726return Data.takeError();1727}1728return Obj.addSection<StringTableSection>();1729case SHT_HASH:1730case SHT_GNU_HASH:1731// Hash tables should refer to SHT_DYNSYM which we're not going to change.1732// Because of this we don't need to mess with the hash tables either.1733if (Expected<ArrayRef<uint8_t>> Data = ElfFile.getSectionContents(Shdr))1734return Obj.addSection<Section>(*Data);1735else1736return Data.takeError();1737case SHT_GROUP:1738if (Expected<ArrayRef<uint8_t>> Data = ElfFile.getSectionContents(Shdr))1739return Obj.addSection<GroupSection>(*Data);1740else1741return Data.takeError();1742case SHT_DYNSYM:1743if (Expected<ArrayRef<uint8_t>> Data = ElfFile.getSectionContents(Shdr))1744return Obj.addSection<DynamicSymbolTableSection>(*Data);1745else1746return Data.takeError();1747case SHT_DYNAMIC:1748if (Expected<ArrayRef<uint8_t>> Data = ElfFile.getSectionContents(Shdr))1749return Obj.addSection<DynamicSection>(*Data);1750else1751return Data.takeError();1752case SHT_SYMTAB: {1753// Multiple SHT_SYMTAB sections are forbidden by the ELF gABI.1754if (Obj.SymbolTable != nullptr)1755return createStringError(llvm::errc::invalid_argument,1756"found multiple SHT_SYMTAB sections");1757auto &SymTab = Obj.addSection<SymbolTableSection>();1758Obj.SymbolTable = &SymTab;1759return SymTab;1760}1761case SHT_SYMTAB_SHNDX: {1762auto &ShndxSection = Obj.addSection<SectionIndexSection>();1763Obj.SectionIndexTable = &ShndxSection;1764return ShndxSection;1765}1766case SHT_NOBITS:1767return Obj.addSection<Section>(ArrayRef<uint8_t>());1768default: {1769Expected<ArrayRef<uint8_t>> Data = ElfFile.getSectionContents(Shdr);1770if (!Data)1771return Data.takeError();17721773Expected<StringRef> Name = ElfFile.getSectionName(Shdr);1774if (!Name)1775return Name.takeError();17761777if (!(Shdr.sh_flags & ELF::SHF_COMPRESSED))1778return Obj.addSection<Section>(*Data);1779auto *Chdr = reinterpret_cast<const Elf_Chdr_Impl<ELFT> *>(Data->data());1780return Obj.addSection<CompressedSection>(CompressedSection(1781*Data, Chdr->ch_type, Chdr->ch_size, Chdr->ch_addralign));1782}1783}1784}17851786template <class ELFT> Error ELFBuilder<ELFT>::readSectionHeaders() {1787uint32_t Index = 0;1788Expected<typename ELFFile<ELFT>::Elf_Shdr_Range> Sections =1789ElfFile.sections();1790if (!Sections)1791return Sections.takeError();17921793for (const typename ELFFile<ELFT>::Elf_Shdr &Shdr : *Sections) {1794if (Index == 0) {1795++Index;1796continue;1797}1798Expected<SectionBase &> Sec = makeSection(Shdr);1799if (!Sec)1800return Sec.takeError();18011802Expected<StringRef> SecName = ElfFile.getSectionName(Shdr);1803if (!SecName)1804return SecName.takeError();1805Sec->Name = SecName->str();1806Sec->Type = Sec->OriginalType = Shdr.sh_type;1807Sec->Flags = Sec->OriginalFlags = Shdr.sh_flags;1808Sec->Addr = Shdr.sh_addr;1809Sec->Offset = Shdr.sh_offset;1810Sec->OriginalOffset = Shdr.sh_offset;1811Sec->Size = Shdr.sh_size;1812Sec->Link = Shdr.sh_link;1813Sec->Info = Shdr.sh_info;1814Sec->Align = Shdr.sh_addralign;1815Sec->EntrySize = Shdr.sh_entsize;1816Sec->Index = Index++;1817Sec->OriginalIndex = Sec->Index;1818Sec->OriginalData = ArrayRef<uint8_t>(1819ElfFile.base() + Shdr.sh_offset,1820(Shdr.sh_type == SHT_NOBITS) ? (size_t)0 : Shdr.sh_size);1821}18221823return Error::success();1824}18251826template <class ELFT> Error ELFBuilder<ELFT>::readSections(bool EnsureSymtab) {1827uint32_t ShstrIndex = ElfFile.getHeader().e_shstrndx;1828if (ShstrIndex == SHN_XINDEX) {1829Expected<const Elf_Shdr *> Sec = ElfFile.getSection(0);1830if (!Sec)1831return Sec.takeError();18321833ShstrIndex = (*Sec)->sh_link;1834}18351836if (ShstrIndex == SHN_UNDEF)1837Obj.HadShdrs = false;1838else {1839Expected<StringTableSection *> Sec =1840Obj.sections().template getSectionOfType<StringTableSection>(1841ShstrIndex,1842"e_shstrndx field value " + Twine(ShstrIndex) + " in elf header " +1843" is invalid",1844"e_shstrndx field value " + Twine(ShstrIndex) + " in elf header " +1845" does not reference a string table");1846if (!Sec)1847return Sec.takeError();18481849Obj.SectionNames = *Sec;1850}18511852// If a section index table exists we'll need to initialize it before we1853// initialize the symbol table because the symbol table might need to1854// reference it.1855if (Obj.SectionIndexTable)1856if (Error Err = Obj.SectionIndexTable->initialize(Obj.sections()))1857return Err;18581859// Now that all of the sections have been added we can fill out some extra1860// details about symbol tables. We need the symbol table filled out before1861// any relocations.1862if (Obj.SymbolTable) {1863if (Error Err = Obj.SymbolTable->initialize(Obj.sections()))1864return Err;1865if (Error Err = initSymbolTable(Obj.SymbolTable))1866return Err;1867} else if (EnsureSymtab) {1868if (Error Err = Obj.addNewSymbolTable())1869return Err;1870}18711872// Now that all sections and symbols have been added we can add1873// relocations that reference symbols and set the link and info fields for1874// relocation sections.1875for (SectionBase &Sec : Obj.sections()) {1876if (&Sec == Obj.SymbolTable)1877continue;1878if (Error Err = Sec.initialize(Obj.sections()))1879return Err;1880if (auto RelSec = dyn_cast<RelocationSection>(&Sec)) {1881Expected<typename ELFFile<ELFT>::Elf_Shdr_Range> Sections =1882ElfFile.sections();1883if (!Sections)1884return Sections.takeError();18851886const typename ELFFile<ELFT>::Elf_Shdr *Shdr =1887Sections->begin() + RelSec->Index;1888if (RelSec->Type == SHT_CREL) {1889auto RelsOrRelas = ElfFile.crels(*Shdr);1890if (!RelsOrRelas)1891return RelsOrRelas.takeError();1892if (Error Err = initRelocations(RelSec, RelsOrRelas->first))1893return Err;1894if (Error Err = initRelocations(RelSec, RelsOrRelas->second))1895return Err;1896} else if (RelSec->Type == SHT_REL) {1897Expected<typename ELFFile<ELFT>::Elf_Rel_Range> Rels =1898ElfFile.rels(*Shdr);1899if (!Rels)1900return Rels.takeError();19011902if (Error Err = initRelocations(RelSec, *Rels))1903return Err;1904} else {1905Expected<typename ELFFile<ELFT>::Elf_Rela_Range> Relas =1906ElfFile.relas(*Shdr);1907if (!Relas)1908return Relas.takeError();19091910if (Error Err = initRelocations(RelSec, *Relas))1911return Err;1912}1913} else if (auto GroupSec = dyn_cast<GroupSection>(&Sec)) {1914if (Error Err = initGroupSection(GroupSec))1915return Err;1916}1917}19181919return Error::success();1920}19211922template <class ELFT> Error ELFBuilder<ELFT>::build(bool EnsureSymtab) {1923if (Error E = readSectionHeaders())1924return E;1925if (Error E = findEhdrOffset())1926return E;19271928// The ELFFile whose ELF headers and program headers are copied into the1929// output file. Normally the same as ElfFile, but if we're extracting a1930// loadable partition it will point to the partition's headers.1931Expected<ELFFile<ELFT>> HeadersFile = ELFFile<ELFT>::create(toStringRef(1932{ElfFile.base() + EhdrOffset, ElfFile.getBufSize() - EhdrOffset}));1933if (!HeadersFile)1934return HeadersFile.takeError();19351936const typename ELFFile<ELFT>::Elf_Ehdr &Ehdr = HeadersFile->getHeader();1937Obj.Is64Bits = Ehdr.e_ident[EI_CLASS] == ELFCLASS64;1938Obj.OSABI = Ehdr.e_ident[EI_OSABI];1939Obj.ABIVersion = Ehdr.e_ident[EI_ABIVERSION];1940Obj.Type = Ehdr.e_type;1941Obj.Machine = Ehdr.e_machine;1942Obj.Version = Ehdr.e_version;1943Obj.Entry = Ehdr.e_entry;1944Obj.Flags = Ehdr.e_flags;19451946if (Error E = readSections(EnsureSymtab))1947return E;1948return readProgramHeaders(*HeadersFile);1949}19501951Writer::~Writer() = default;19521953Reader::~Reader() = default;19541955Expected<std::unique_ptr<Object>>1956BinaryReader::create(bool /*EnsureSymtab*/) const {1957return BinaryELFBuilder(MemBuf, NewSymbolVisibility).build();1958}19591960Expected<std::vector<IHexRecord>> IHexReader::parse() const {1961SmallVector<StringRef, 16> Lines;1962std::vector<IHexRecord> Records;1963bool HasSections = false;19641965MemBuf->getBuffer().split(Lines, '\n');1966Records.reserve(Lines.size());1967for (size_t LineNo = 1; LineNo <= Lines.size(); ++LineNo) {1968StringRef Line = Lines[LineNo - 1].trim();1969if (Line.empty())1970continue;19711972Expected<IHexRecord> R = IHexRecord::parse(Line);1973if (!R)1974return parseError(LineNo, R.takeError());1975if (R->Type == IHexRecord::EndOfFile)1976break;1977HasSections |= (R->Type == IHexRecord::Data);1978Records.push_back(*R);1979}1980if (!HasSections)1981return parseError(-1U, "no sections");19821983return std::move(Records);1984}19851986Expected<std::unique_ptr<Object>>1987IHexReader::create(bool /*EnsureSymtab*/) const {1988Expected<std::vector<IHexRecord>> Records = parse();1989if (!Records)1990return Records.takeError();19911992return IHexELFBuilder(*Records).build();1993}19941995Expected<std::unique_ptr<Object>> ELFReader::create(bool EnsureSymtab) const {1996auto Obj = std::make_unique<Object>();1997if (auto *O = dyn_cast<ELFObjectFile<ELF32LE>>(Bin)) {1998ELFBuilder<ELF32LE> Builder(*O, *Obj, ExtractPartition);1999if (Error Err = Builder.build(EnsureSymtab))2000return std::move(Err);2001return std::move(Obj);2002} else if (auto *O = dyn_cast<ELFObjectFile<ELF64LE>>(Bin)) {2003ELFBuilder<ELF64LE> Builder(*O, *Obj, ExtractPartition);2004if (Error Err = Builder.build(EnsureSymtab))2005return std::move(Err);2006return std::move(Obj);2007} else if (auto *O = dyn_cast<ELFObjectFile<ELF32BE>>(Bin)) {2008ELFBuilder<ELF32BE> Builder(*O, *Obj, ExtractPartition);2009if (Error Err = Builder.build(EnsureSymtab))2010return std::move(Err);2011return std::move(Obj);2012} else if (auto *O = dyn_cast<ELFObjectFile<ELF64BE>>(Bin)) {2013ELFBuilder<ELF64BE> Builder(*O, *Obj, ExtractPartition);2014if (Error Err = Builder.build(EnsureSymtab))2015return std::move(Err);2016return std::move(Obj);2017}2018return createStringError(errc::invalid_argument, "invalid file type");2019}20202021template <class ELFT> void ELFWriter<ELFT>::writeEhdr() {2022Elf_Ehdr &Ehdr = *reinterpret_cast<Elf_Ehdr *>(Buf->getBufferStart());2023std::fill(Ehdr.e_ident, Ehdr.e_ident + 16, 0);2024Ehdr.e_ident[EI_MAG0] = 0x7f;2025Ehdr.e_ident[EI_MAG1] = 'E';2026Ehdr.e_ident[EI_MAG2] = 'L';2027Ehdr.e_ident[EI_MAG3] = 'F';2028Ehdr.e_ident[EI_CLASS] = ELFT::Is64Bits ? ELFCLASS64 : ELFCLASS32;2029Ehdr.e_ident[EI_DATA] =2030ELFT::Endianness == llvm::endianness::big ? ELFDATA2MSB : ELFDATA2LSB;2031Ehdr.e_ident[EI_VERSION] = EV_CURRENT;2032Ehdr.e_ident[EI_OSABI] = Obj.OSABI;2033Ehdr.e_ident[EI_ABIVERSION] = Obj.ABIVersion;20342035Ehdr.e_type = Obj.Type;2036Ehdr.e_machine = Obj.Machine;2037Ehdr.e_version = Obj.Version;2038Ehdr.e_entry = Obj.Entry;2039// We have to use the fully-qualified name llvm::size2040// since some compilers complain on ambiguous resolution.2041Ehdr.e_phnum = llvm::size(Obj.segments());2042Ehdr.e_phoff = (Ehdr.e_phnum != 0) ? Obj.ProgramHdrSegment.Offset : 0;2043Ehdr.e_phentsize = (Ehdr.e_phnum != 0) ? sizeof(Elf_Phdr) : 0;2044Ehdr.e_flags = Obj.Flags;2045Ehdr.e_ehsize = sizeof(Elf_Ehdr);2046if (WriteSectionHeaders && Obj.sections().size() != 0) {2047Ehdr.e_shentsize = sizeof(Elf_Shdr);2048Ehdr.e_shoff = Obj.SHOff;2049// """2050// If the number of sections is greater than or equal to2051// SHN_LORESERVE (0xff00), this member has the value zero and the actual2052// number of section header table entries is contained in the sh_size field2053// of the section header at index 0.2054// """2055auto Shnum = Obj.sections().size() + 1;2056if (Shnum >= SHN_LORESERVE)2057Ehdr.e_shnum = 0;2058else2059Ehdr.e_shnum = Shnum;2060// """2061// If the section name string table section index is greater than or equal2062// to SHN_LORESERVE (0xff00), this member has the value SHN_XINDEX (0xffff)2063// and the actual index of the section name string table section is2064// contained in the sh_link field of the section header at index 0.2065// """2066if (Obj.SectionNames->Index >= SHN_LORESERVE)2067Ehdr.e_shstrndx = SHN_XINDEX;2068else2069Ehdr.e_shstrndx = Obj.SectionNames->Index;2070} else {2071Ehdr.e_shentsize = 0;2072Ehdr.e_shoff = 0;2073Ehdr.e_shnum = 0;2074Ehdr.e_shstrndx = 0;2075}2076}20772078template <class ELFT> void ELFWriter<ELFT>::writePhdrs() {2079for (auto &Seg : Obj.segments())2080writePhdr(Seg);2081}20822083template <class ELFT> void ELFWriter<ELFT>::writeShdrs() {2084// This reference serves to write the dummy section header at the begining2085// of the file. It is not used for anything else2086Elf_Shdr &Shdr =2087*reinterpret_cast<Elf_Shdr *>(Buf->getBufferStart() + Obj.SHOff);2088Shdr.sh_name = 0;2089Shdr.sh_type = SHT_NULL;2090Shdr.sh_flags = 0;2091Shdr.sh_addr = 0;2092Shdr.sh_offset = 0;2093// See writeEhdr for why we do this.2094uint64_t Shnum = Obj.sections().size() + 1;2095if (Shnum >= SHN_LORESERVE)2096Shdr.sh_size = Shnum;2097else2098Shdr.sh_size = 0;2099// See writeEhdr for why we do this.2100if (Obj.SectionNames != nullptr && Obj.SectionNames->Index >= SHN_LORESERVE)2101Shdr.sh_link = Obj.SectionNames->Index;2102else2103Shdr.sh_link = 0;2104Shdr.sh_info = 0;2105Shdr.sh_addralign = 0;2106Shdr.sh_entsize = 0;21072108for (SectionBase &Sec : Obj.sections())2109writeShdr(Sec);2110}21112112template <class ELFT> Error ELFWriter<ELFT>::writeSectionData() {2113for (SectionBase &Sec : Obj.sections())2114// Segments are responsible for writing their contents, so only write the2115// section data if the section is not in a segment. Note that this renders2116// sections in segments effectively immutable.2117if (Sec.ParentSegment == nullptr)2118if (Error Err = Sec.accept(*SecWriter))2119return Err;21202121return Error::success();2122}21232124template <class ELFT> void ELFWriter<ELFT>::writeSegmentData() {2125for (Segment &Seg : Obj.segments()) {2126size_t Size = std::min<size_t>(Seg.FileSize, Seg.getContents().size());2127std::memcpy(Buf->getBufferStart() + Seg.Offset, Seg.getContents().data(),2128Size);2129}21302131for (const auto &it : Obj.getUpdatedSections()) {2132SectionBase *Sec = it.first;2133ArrayRef<uint8_t> Data = it.second;21342135auto *Parent = Sec->ParentSegment;2136assert(Parent && "This section should've been part of a segment.");2137uint64_t Offset =2138Sec->OriginalOffset - Parent->OriginalOffset + Parent->Offset;2139llvm::copy(Data, Buf->getBufferStart() + Offset);2140}21412142// Iterate over removed sections and overwrite their old data with zeroes.2143for (auto &Sec : Obj.removedSections()) {2144Segment *Parent = Sec.ParentSegment;2145if (Parent == nullptr || Sec.Type == SHT_NOBITS || Sec.Size == 0)2146continue;2147uint64_t Offset =2148Sec.OriginalOffset - Parent->OriginalOffset + Parent->Offset;2149std::memset(Buf->getBufferStart() + Offset, 0, Sec.Size);2150}2151}21522153template <class ELFT>2154ELFWriter<ELFT>::ELFWriter(Object &Obj, raw_ostream &Buf, bool WSH,2155bool OnlyKeepDebug)2156: Writer(Obj, Buf), WriteSectionHeaders(WSH && Obj.HadShdrs),2157OnlyKeepDebug(OnlyKeepDebug) {}21582159Error Object::updateSection(StringRef Name, ArrayRef<uint8_t> Data) {2160auto It = llvm::find_if(Sections,2161[&](const SecPtr &Sec) { return Sec->Name == Name; });2162if (It == Sections.end())2163return createStringError(errc::invalid_argument, "section '%s' not found",2164Name.str().c_str());21652166auto *OldSec = It->get();2167if (!OldSec->hasContents())2168return createStringError(2169errc::invalid_argument,2170"section '%s' cannot be updated because it does not have contents",2171Name.str().c_str());21722173if (Data.size() > OldSec->Size && OldSec->ParentSegment)2174return createStringError(errc::invalid_argument,2175"cannot fit data of size %zu into section '%s' "2176"with size %" PRIu64 " that is part of a segment",2177Data.size(), Name.str().c_str(), OldSec->Size);21782179if (!OldSec->ParentSegment) {2180*It = std::make_unique<OwnedDataSection>(*OldSec, Data);2181} else {2182// The segment writer will be in charge of updating these contents.2183OldSec->Size = Data.size();2184UpdatedSections[OldSec] = Data;2185}21862187return Error::success();2188}21892190Error Object::removeSections(2191bool AllowBrokenLinks, std::function<bool(const SectionBase &)> ToRemove) {21922193auto Iter = std::stable_partition(2194std::begin(Sections), std::end(Sections), [=](const SecPtr &Sec) {2195if (ToRemove(*Sec))2196return false;2197// TODO: A compressed relocation section may be recognized as2198// RelocationSectionBase. We don't want such a section to be removed.2199if (isa<CompressedSection>(Sec))2200return true;2201if (auto RelSec = dyn_cast<RelocationSectionBase>(Sec.get())) {2202if (auto ToRelSec = RelSec->getSection())2203return !ToRemove(*ToRelSec);2204}2205// Remove empty group sections.2206if (Sec->Type == ELF::SHT_GROUP) {2207auto GroupSec = cast<GroupSection>(Sec.get());2208return !llvm::all_of(GroupSec->members(), ToRemove);2209}2210return true;2211});2212if (SymbolTable != nullptr && ToRemove(*SymbolTable))2213SymbolTable = nullptr;2214if (SectionNames != nullptr && ToRemove(*SectionNames))2215SectionNames = nullptr;2216if (SectionIndexTable != nullptr && ToRemove(*SectionIndexTable))2217SectionIndexTable = nullptr;2218// Now make sure there are no remaining references to the sections that will2219// be removed. Sometimes it is impossible to remove a reference so we emit2220// an error here instead.2221std::unordered_set<const SectionBase *> RemoveSections;2222RemoveSections.reserve(std::distance(Iter, std::end(Sections)));2223for (auto &RemoveSec : make_range(Iter, std::end(Sections))) {2224for (auto &Segment : Segments)2225Segment->removeSection(RemoveSec.get());2226RemoveSec->onRemove();2227RemoveSections.insert(RemoveSec.get());2228}22292230// For each section that remains alive, we want to remove the dead references.2231// This either might update the content of the section (e.g. remove symbols2232// from symbol table that belongs to removed section) or trigger an error if2233// a live section critically depends on a section being removed somehow2234// (e.g. the removed section is referenced by a relocation).2235for (auto &KeepSec : make_range(std::begin(Sections), Iter)) {2236if (Error E = KeepSec->removeSectionReferences(2237AllowBrokenLinks, [&RemoveSections](const SectionBase *Sec) {2238return RemoveSections.find(Sec) != RemoveSections.end();2239}))2240return E;2241}22422243// Transfer removed sections into the Object RemovedSections container for use2244// later.2245std::move(Iter, Sections.end(), std::back_inserter(RemovedSections));2246// Now finally get rid of them all together.2247Sections.erase(Iter, std::end(Sections));2248return Error::success();2249}22502251Error Object::replaceSections(2252const DenseMap<SectionBase *, SectionBase *> &FromTo) {2253auto SectionIndexLess = [](const SecPtr &Lhs, const SecPtr &Rhs) {2254return Lhs->Index < Rhs->Index;2255};2256assert(llvm::is_sorted(Sections, SectionIndexLess) &&2257"Sections are expected to be sorted by Index");2258// Set indices of new sections so that they can be later sorted into positions2259// of removed ones.2260for (auto &I : FromTo)2261I.second->Index = I.first->Index;22622263// Notify all sections about the replacement.2264for (auto &Sec : Sections)2265Sec->replaceSectionReferences(FromTo);22662267if (Error E = removeSections(2268/*AllowBrokenLinks=*/false,2269[=](const SectionBase &Sec) { return FromTo.count(&Sec) > 0; }))2270return E;2271llvm::sort(Sections, SectionIndexLess);2272return Error::success();2273}22742275Error Object::removeSymbols(function_ref<bool(const Symbol &)> ToRemove) {2276if (SymbolTable)2277for (const SecPtr &Sec : Sections)2278if (Error E = Sec->removeSymbols(ToRemove))2279return E;2280return Error::success();2281}22822283Error Object::addNewSymbolTable() {2284assert(!SymbolTable && "Object must not has a SymbolTable.");22852286// Reuse an existing SHT_STRTAB section if it exists.2287StringTableSection *StrTab = nullptr;2288for (SectionBase &Sec : sections()) {2289if (Sec.Type == ELF::SHT_STRTAB && !(Sec.Flags & SHF_ALLOC)) {2290StrTab = static_cast<StringTableSection *>(&Sec);22912292// Prefer a string table that is not the section header string table, if2293// such a table exists.2294if (SectionNames != &Sec)2295break;2296}2297}2298if (!StrTab)2299StrTab = &addSection<StringTableSection>();23002301SymbolTableSection &SymTab = addSection<SymbolTableSection>();2302SymTab.Name = ".symtab";2303SymTab.Link = StrTab->Index;2304if (Error Err = SymTab.initialize(sections()))2305return Err;2306SymTab.addSymbol("", 0, 0, nullptr, 0, 0, 0, 0);23072308SymbolTable = &SymTab;23092310return Error::success();2311}23122313// Orders segments such that if x = y->ParentSegment then y comes before x.2314static void orderSegments(std::vector<Segment *> &Segments) {2315llvm::stable_sort(Segments, compareSegmentsByOffset);2316}23172318// This function finds a consistent layout for a list of segments starting from2319// an Offset. It assumes that Segments have been sorted by orderSegments and2320// returns an Offset one past the end of the last segment.2321static uint64_t layoutSegments(std::vector<Segment *> &Segments,2322uint64_t Offset) {2323assert(llvm::is_sorted(Segments, compareSegmentsByOffset));2324// The only way a segment should move is if a section was between two2325// segments and that section was removed. If that section isn't in a segment2326// then it's acceptable, but not ideal, to simply move it to after the2327// segments. So we can simply layout segments one after the other accounting2328// for alignment.2329for (Segment *Seg : Segments) {2330// We assume that segments have been ordered by OriginalOffset and Index2331// such that a parent segment will always come before a child segment in2332// OrderedSegments. This means that the Offset of the ParentSegment should2333// already be set and we can set our offset relative to it.2334if (Seg->ParentSegment != nullptr) {2335Segment *Parent = Seg->ParentSegment;2336Seg->Offset =2337Parent->Offset + Seg->OriginalOffset - Parent->OriginalOffset;2338} else {2339Seg->Offset =2340alignTo(Offset, std::max<uint64_t>(Seg->Align, 1), Seg->VAddr);2341}2342Offset = std::max(Offset, Seg->Offset + Seg->FileSize);2343}2344return Offset;2345}23462347// This function finds a consistent layout for a list of sections. It assumes2348// that the ->ParentSegment of each section has already been laid out. The2349// supplied starting Offset is used for the starting offset of any section that2350// does not have a ParentSegment. It returns either the offset given if all2351// sections had a ParentSegment or an offset one past the last section if there2352// was a section that didn't have a ParentSegment.2353template <class Range>2354static uint64_t layoutSections(Range Sections, uint64_t Offset) {2355// Now the offset of every segment has been set we can assign the offsets2356// of each section. For sections that are covered by a segment we should use2357// the segment's original offset and the section's original offset to compute2358// the offset from the start of the segment. Using the offset from the start2359// of the segment we can assign a new offset to the section. For sections not2360// covered by segments we can just bump Offset to the next valid location.2361// While it is not necessary, layout the sections in the order based on their2362// original offsets to resemble the input file as close as possible.2363std::vector<SectionBase *> OutOfSegmentSections;2364uint32_t Index = 1;2365for (auto &Sec : Sections) {2366Sec.Index = Index++;2367if (Sec.ParentSegment != nullptr) {2368const Segment &Segment = *Sec.ParentSegment;2369Sec.Offset =2370Segment.Offset + (Sec.OriginalOffset - Segment.OriginalOffset);2371} else2372OutOfSegmentSections.push_back(&Sec);2373}23742375llvm::stable_sort(OutOfSegmentSections,2376[](const SectionBase *Lhs, const SectionBase *Rhs) {2377return Lhs->OriginalOffset < Rhs->OriginalOffset;2378});2379for (auto *Sec : OutOfSegmentSections) {2380Offset = alignTo(Offset, Sec->Align == 0 ? 1 : Sec->Align);2381Sec->Offset = Offset;2382if (Sec->Type != SHT_NOBITS)2383Offset += Sec->Size;2384}2385return Offset;2386}23872388// Rewrite sh_offset after some sections are changed to SHT_NOBITS and thus2389// occupy no space in the file.2390static uint64_t layoutSectionsForOnlyKeepDebug(Object &Obj, uint64_t Off) {2391// The layout algorithm requires the sections to be handled in the order of2392// their offsets in the input file, at least inside segments.2393std::vector<SectionBase *> Sections;2394Sections.reserve(Obj.sections().size());2395uint32_t Index = 1;2396for (auto &Sec : Obj.sections()) {2397Sec.Index = Index++;2398Sections.push_back(&Sec);2399}2400llvm::stable_sort(Sections,2401[](const SectionBase *Lhs, const SectionBase *Rhs) {2402return Lhs->OriginalOffset < Rhs->OriginalOffset;2403});24042405for (auto *Sec : Sections) {2406auto *FirstSec = Sec->ParentSegment && Sec->ParentSegment->Type == PT_LOAD2407? Sec->ParentSegment->firstSection()2408: nullptr;24092410// The first section in a PT_LOAD has to have congruent offset and address2411// modulo the alignment, which usually equals the maximum page size.2412if (FirstSec && FirstSec == Sec)2413Off = alignTo(Off, Sec->ParentSegment->Align, Sec->Addr);24142415// sh_offset is not significant for SHT_NOBITS sections, but the congruence2416// rule must be followed if it is the first section in a PT_LOAD. Do not2417// advance Off.2418if (Sec->Type == SHT_NOBITS) {2419Sec->Offset = Off;2420continue;2421}24222423if (!FirstSec) {2424// FirstSec being nullptr generally means that Sec does not have the2425// SHF_ALLOC flag.2426Off = Sec->Align ? alignTo(Off, Sec->Align) : Off;2427} else if (FirstSec != Sec) {2428// The offset is relative to the first section in the PT_LOAD segment. Use2429// sh_offset for non-SHF_ALLOC sections.2430Off = Sec->OriginalOffset - FirstSec->OriginalOffset + FirstSec->Offset;2431}2432Sec->Offset = Off;2433Off += Sec->Size;2434}2435return Off;2436}24372438// Rewrite p_offset and p_filesz of non-PT_PHDR segments after sh_offset values2439// have been updated.2440static uint64_t layoutSegmentsForOnlyKeepDebug(std::vector<Segment *> &Segments,2441uint64_t HdrEnd) {2442uint64_t MaxOffset = 0;2443for (Segment *Seg : Segments) {2444if (Seg->Type == PT_PHDR)2445continue;24462447// The segment offset is generally the offset of the first section.2448//2449// For a segment containing no section (see sectionWithinSegment), if it has2450// a parent segment, copy the parent segment's offset field. This works for2451// empty PT_TLS. If no parent segment, use 0: the segment is not useful for2452// debugging anyway.2453const SectionBase *FirstSec = Seg->firstSection();2454uint64_t Offset =2455FirstSec ? FirstSec->Offset2456: (Seg->ParentSegment ? Seg->ParentSegment->Offset : 0);2457uint64_t FileSize = 0;2458for (const SectionBase *Sec : Seg->Sections) {2459uint64_t Size = Sec->Type == SHT_NOBITS ? 0 : Sec->Size;2460if (Sec->Offset + Size > Offset)2461FileSize = std::max(FileSize, Sec->Offset + Size - Offset);2462}24632464// If the segment includes EHDR and program headers, don't make it smaller2465// than the headers.2466if (Seg->Offset < HdrEnd && HdrEnd <= Seg->Offset + Seg->FileSize) {2467FileSize += Offset - Seg->Offset;2468Offset = Seg->Offset;2469FileSize = std::max(FileSize, HdrEnd - Offset);2470}24712472Seg->Offset = Offset;2473Seg->FileSize = FileSize;2474MaxOffset = std::max(MaxOffset, Offset + FileSize);2475}2476return MaxOffset;2477}24782479template <class ELFT> void ELFWriter<ELFT>::initEhdrSegment() {2480Segment &ElfHdr = Obj.ElfHdrSegment;2481ElfHdr.Type = PT_PHDR;2482ElfHdr.Flags = 0;2483ElfHdr.VAddr = 0;2484ElfHdr.PAddr = 0;2485ElfHdr.FileSize = ElfHdr.MemSize = sizeof(Elf_Ehdr);2486ElfHdr.Align = 0;2487}24882489template <class ELFT> void ELFWriter<ELFT>::assignOffsets() {2490// We need a temporary list of segments that has a special order to it2491// so that we know that anytime ->ParentSegment is set that segment has2492// already had its offset properly set.2493std::vector<Segment *> OrderedSegments;2494for (Segment &Segment : Obj.segments())2495OrderedSegments.push_back(&Segment);2496OrderedSegments.push_back(&Obj.ElfHdrSegment);2497OrderedSegments.push_back(&Obj.ProgramHdrSegment);2498orderSegments(OrderedSegments);24992500uint64_t Offset;2501if (OnlyKeepDebug) {2502// For --only-keep-debug, the sections that did not preserve contents were2503// changed to SHT_NOBITS. We now rewrite sh_offset fields of sections, and2504// then rewrite p_offset/p_filesz of program headers.2505uint64_t HdrEnd =2506sizeof(Elf_Ehdr) + llvm::size(Obj.segments()) * sizeof(Elf_Phdr);2507Offset = layoutSectionsForOnlyKeepDebug(Obj, HdrEnd);2508Offset = std::max(Offset,2509layoutSegmentsForOnlyKeepDebug(OrderedSegments, HdrEnd));2510} else {2511// Offset is used as the start offset of the first segment to be laid out.2512// Since the ELF Header (ElfHdrSegment) must be at the start of the file,2513// we start at offset 0.2514Offset = layoutSegments(OrderedSegments, 0);2515Offset = layoutSections(Obj.sections(), Offset);2516}2517// If we need to write the section header table out then we need to align the2518// Offset so that SHOffset is valid.2519if (WriteSectionHeaders)2520Offset = alignTo(Offset, sizeof(Elf_Addr));2521Obj.SHOff = Offset;2522}25232524template <class ELFT> size_t ELFWriter<ELFT>::totalSize() const {2525// We already have the section header offset so we can calculate the total2526// size by just adding up the size of each section header.2527if (!WriteSectionHeaders)2528return Obj.SHOff;2529size_t ShdrCount = Obj.sections().size() + 1; // Includes null shdr.2530return Obj.SHOff + ShdrCount * sizeof(Elf_Shdr);2531}25322533template <class ELFT> Error ELFWriter<ELFT>::write() {2534// Segment data must be written first, so that the ELF header and program2535// header tables can overwrite it, if covered by a segment.2536writeSegmentData();2537writeEhdr();2538writePhdrs();2539if (Error E = writeSectionData())2540return E;2541if (WriteSectionHeaders)2542writeShdrs();25432544// TODO: Implement direct writing to the output stream (without intermediate2545// memory buffer Buf).2546Out.write(Buf->getBufferStart(), Buf->getBufferSize());2547return Error::success();2548}25492550static Error removeUnneededSections(Object &Obj) {2551// We can remove an empty symbol table from non-relocatable objects.2552// Relocatable objects typically have relocation sections whose2553// sh_link field points to .symtab, so we can't remove .symtab2554// even if it is empty.2555if (Obj.isRelocatable() || Obj.SymbolTable == nullptr ||2556!Obj.SymbolTable->empty())2557return Error::success();25582559// .strtab can be used for section names. In such a case we shouldn't2560// remove it.2561auto *StrTab = Obj.SymbolTable->getStrTab() == Obj.SectionNames2562? nullptr2563: Obj.SymbolTable->getStrTab();2564return Obj.removeSections(false, [&](const SectionBase &Sec) {2565return &Sec == Obj.SymbolTable || &Sec == StrTab;2566});2567}25682569template <class ELFT> Error ELFWriter<ELFT>::finalize() {2570// It could happen that SectionNames has been removed and yet the user wants2571// a section header table output. We need to throw an error if a user tries2572// to do that.2573if (Obj.SectionNames == nullptr && WriteSectionHeaders)2574return createStringError(llvm::errc::invalid_argument,2575"cannot write section header table because "2576"section header string table was removed");25772578if (Error E = removeUnneededSections(Obj))2579return E;25802581// If the .symtab indices have not been changed, restore the sh_link to2582// .symtab for sections that were linked to .symtab.2583if (Obj.SymbolTable && !Obj.SymbolTable->indicesChanged())2584for (SectionBase &Sec : Obj.sections())2585Sec.restoreSymTabLink(*Obj.SymbolTable);25862587// We need to assign indexes before we perform layout because we need to know2588// if we need large indexes or not. We can assign indexes first and check as2589// we go to see if we will actully need large indexes.2590bool NeedsLargeIndexes = false;2591if (Obj.sections().size() >= SHN_LORESERVE) {2592SectionTableRef Sections = Obj.sections();2593// Sections doesn't include the null section header, so account for this2594// when skipping the first N sections.2595NeedsLargeIndexes =2596any_of(drop_begin(Sections, SHN_LORESERVE - 1),2597[](const SectionBase &Sec) { return Sec.HasSymbol; });2598// TODO: handle case where only one section needs the large index table but2599// only needs it because the large index table hasn't been removed yet.2600}26012602if (NeedsLargeIndexes) {2603// This means we definitely need to have a section index table but if we2604// already have one then we should use it instead of making a new one.2605if (Obj.SymbolTable != nullptr && Obj.SectionIndexTable == nullptr) {2606// Addition of a section to the end does not invalidate the indexes of2607// other sections and assigns the correct index to the new section.2608auto &Shndx = Obj.addSection<SectionIndexSection>();2609Obj.SymbolTable->setShndxTable(&Shndx);2610Shndx.setSymTab(Obj.SymbolTable);2611}2612} else {2613// Since we don't need SectionIndexTable we should remove it and all2614// references to it.2615if (Obj.SectionIndexTable != nullptr) {2616// We do not support sections referring to the section index table.2617if (Error E = Obj.removeSections(false /*AllowBrokenLinks*/,2618[this](const SectionBase &Sec) {2619return &Sec == Obj.SectionIndexTable;2620}))2621return E;2622}2623}26242625// Make sure we add the names of all the sections. Importantly this must be2626// done after we decide to add or remove SectionIndexes.2627if (Obj.SectionNames != nullptr)2628for (const SectionBase &Sec : Obj.sections())2629Obj.SectionNames->addString(Sec.Name);26302631initEhdrSegment();26322633// Before we can prepare for layout the indexes need to be finalized.2634// Also, the output arch may not be the same as the input arch, so fix up2635// size-related fields before doing layout calculations.2636uint64_t Index = 0;2637auto SecSizer = std::make_unique<ELFSectionSizer<ELFT>>();2638for (SectionBase &Sec : Obj.sections()) {2639Sec.Index = Index++;2640if (Error Err = Sec.accept(*SecSizer))2641return Err;2642}26432644// The symbol table does not update all other sections on update. For2645// instance, symbol names are not added as new symbols are added. This means2646// that some sections, like .strtab, don't yet have their final size.2647if (Obj.SymbolTable != nullptr)2648Obj.SymbolTable->prepareForLayout();26492650// Now that all strings are added we want to finalize string table builders,2651// because that affects section sizes which in turn affects section offsets.2652for (SectionBase &Sec : Obj.sections())2653if (auto StrTab = dyn_cast<StringTableSection>(&Sec))2654StrTab->prepareForLayout();26552656assignOffsets();26572658// layoutSections could have modified section indexes, so we need2659// to fill the index table after assignOffsets.2660if (Obj.SymbolTable != nullptr)2661Obj.SymbolTable->fillShndxTable();26622663// Finally now that all offsets and indexes have been set we can finalize any2664// remaining issues.2665uint64_t Offset = Obj.SHOff + sizeof(Elf_Shdr);2666for (SectionBase &Sec : Obj.sections()) {2667Sec.HeaderOffset = Offset;2668Offset += sizeof(Elf_Shdr);2669if (WriteSectionHeaders)2670Sec.NameIndex = Obj.SectionNames->findIndex(Sec.Name);2671Sec.finalize();2672}26732674size_t TotalSize = totalSize();2675Buf = WritableMemoryBuffer::getNewMemBuffer(TotalSize);2676if (!Buf)2677return createStringError(errc::not_enough_memory,2678"failed to allocate memory buffer of " +2679Twine::utohexstr(TotalSize) + " bytes");26802681SecWriter = std::make_unique<ELFSectionWriter<ELFT>>(*Buf);2682return Error::success();2683}26842685Error BinaryWriter::write() {2686SmallVector<const SectionBase *, 30> SectionsToWrite;2687for (const SectionBase &Sec : Obj.allocSections()) {2688if (Sec.Type != SHT_NOBITS && Sec.Size > 0)2689SectionsToWrite.push_back(&Sec);2690}26912692if (SectionsToWrite.empty())2693return Error::success();26942695llvm::stable_sort(SectionsToWrite,2696[](const SectionBase *LHS, const SectionBase *RHS) {2697return LHS->Offset < RHS->Offset;2698});26992700assert(SectionsToWrite.front()->Offset == 0);27012702for (size_t i = 0; i != SectionsToWrite.size(); ++i) {2703const SectionBase &Sec = *SectionsToWrite[i];2704if (Error Err = Sec.accept(*SecWriter))2705return Err;2706if (GapFill == 0)2707continue;2708uint64_t PadOffset = (i < SectionsToWrite.size() - 1)2709? SectionsToWrite[i + 1]->Offset2710: Buf->getBufferSize();2711assert(PadOffset <= Buf->getBufferSize());2712assert(Sec.Offset + Sec.Size <= PadOffset);2713std::fill(Buf->getBufferStart() + Sec.Offset + Sec.Size,2714Buf->getBufferStart() + PadOffset, GapFill);2715}27162717// TODO: Implement direct writing to the output stream (without intermediate2718// memory buffer Buf).2719Out.write(Buf->getBufferStart(), Buf->getBufferSize());2720return Error::success();2721}27222723Error BinaryWriter::finalize() {2724// Compute the section LMA based on its sh_offset and the containing segment's2725// p_offset and p_paddr. Also compute the minimum LMA of all non-empty2726// sections as MinAddr. In the output, the contents between address 0 and2727// MinAddr will be skipped.2728uint64_t MinAddr = UINT64_MAX;2729for (SectionBase &Sec : Obj.allocSections()) {2730if (Sec.ParentSegment != nullptr)2731Sec.Addr =2732Sec.Offset - Sec.ParentSegment->Offset + Sec.ParentSegment->PAddr;2733if (Sec.Type != SHT_NOBITS && Sec.Size > 0)2734MinAddr = std::min(MinAddr, Sec.Addr);2735}27362737// Now that every section has been laid out we just need to compute the total2738// file size. This might not be the same as the offset returned by2739// layoutSections, because we want to truncate the last segment to the end of2740// its last non-empty section, to match GNU objcopy's behaviour.2741TotalSize = PadTo > MinAddr ? PadTo - MinAddr : 0;2742for (SectionBase &Sec : Obj.allocSections())2743if (Sec.Type != SHT_NOBITS && Sec.Size > 0) {2744Sec.Offset = Sec.Addr - MinAddr;2745TotalSize = std::max(TotalSize, Sec.Offset + Sec.Size);2746}27472748Buf = WritableMemoryBuffer::getNewMemBuffer(TotalSize);2749if (!Buf)2750return createStringError(errc::not_enough_memory,2751"failed to allocate memory buffer of " +2752Twine::utohexstr(TotalSize) + " bytes");2753SecWriter = std::make_unique<BinarySectionWriter>(*Buf);2754return Error::success();2755}27562757Error ASCIIHexWriter::checkSection(const SectionBase &S) const {2758if (addressOverflows32bit(S.Addr) ||2759addressOverflows32bit(S.Addr + S.Size - 1))2760return createStringError(2761errc::invalid_argument,2762"section '%s' address range [0x%llx, 0x%llx] is not 32 bit",2763S.Name.c_str(), S.Addr, S.Addr + S.Size - 1);2764return Error::success();2765}27662767Error ASCIIHexWriter::finalize() {2768// We can't write 64-bit addresses.2769if (addressOverflows32bit(Obj.Entry))2770return createStringError(errc::invalid_argument,2771"entry point address 0x%llx overflows 32 bits",2772Obj.Entry);27732774for (const SectionBase &S : Obj.sections()) {2775if ((S.Flags & ELF::SHF_ALLOC) && S.Type != ELF::SHT_NOBITS && S.Size > 0) {2776if (Error E = checkSection(S))2777return E;2778Sections.push_back(&S);2779}2780}27812782llvm::sort(Sections, [](const SectionBase *A, const SectionBase *B) {2783return sectionPhysicalAddr(A) < sectionPhysicalAddr(B);2784});27852786std::unique_ptr<WritableMemoryBuffer> EmptyBuffer =2787WritableMemoryBuffer::getNewMemBuffer(0);2788if (!EmptyBuffer)2789return createStringError(errc::not_enough_memory,2790"failed to allocate memory buffer of 0 bytes");27912792Expected<size_t> ExpTotalSize = getTotalSize(*EmptyBuffer);2793if (!ExpTotalSize)2794return ExpTotalSize.takeError();2795TotalSize = *ExpTotalSize;27962797Buf = WritableMemoryBuffer::getNewMemBuffer(TotalSize);2798if (!Buf)2799return createStringError(errc::not_enough_memory,2800"failed to allocate memory buffer of 0x" +2801Twine::utohexstr(TotalSize) + " bytes");2802return Error::success();2803}28042805uint64_t IHexWriter::writeEntryPointRecord(uint8_t *Buf) {2806IHexLineData HexData;2807uint8_t Data[4] = {};2808// We don't write entry point record if entry is zero.2809if (Obj.Entry == 0)2810return 0;28112812if (Obj.Entry <= 0xFFFFFU) {2813Data[0] = ((Obj.Entry & 0xF0000U) >> 12) & 0xFF;2814support::endian::write(&Data[2], static_cast<uint16_t>(Obj.Entry),2815llvm::endianness::big);2816HexData = IHexRecord::getLine(IHexRecord::StartAddr80x86, 0, Data);2817} else {2818support::endian::write(Data, static_cast<uint32_t>(Obj.Entry),2819llvm::endianness::big);2820HexData = IHexRecord::getLine(IHexRecord::StartAddr, 0, Data);2821}2822memcpy(Buf, HexData.data(), HexData.size());2823return HexData.size();2824}28252826uint64_t IHexWriter::writeEndOfFileRecord(uint8_t *Buf) {2827IHexLineData HexData = IHexRecord::getLine(IHexRecord::EndOfFile, 0, {});2828memcpy(Buf, HexData.data(), HexData.size());2829return HexData.size();2830}28312832Expected<size_t>2833IHexWriter::getTotalSize(WritableMemoryBuffer &EmptyBuffer) const {2834IHexSectionWriterBase LengthCalc(EmptyBuffer);2835for (const SectionBase *Sec : Sections)2836if (Error Err = Sec->accept(LengthCalc))2837return std::move(Err);28382839// We need space to write section records + StartAddress record2840// (if start adress is not zero) + EndOfFile record.2841return LengthCalc.getBufferOffset() +2842(Obj.Entry ? IHexRecord::getLineLength(4) : 0) +2843IHexRecord::getLineLength(0);2844}28452846Error IHexWriter::write() {2847IHexSectionWriter Writer(*Buf);2848// Write sections.2849for (const SectionBase *Sec : Sections)2850if (Error Err = Sec->accept(Writer))2851return Err;28522853uint64_t Offset = Writer.getBufferOffset();2854// Write entry point address.2855Offset += writeEntryPointRecord(2856reinterpret_cast<uint8_t *>(Buf->getBufferStart()) + Offset);2857// Write EOF.2858Offset += writeEndOfFileRecord(2859reinterpret_cast<uint8_t *>(Buf->getBufferStart()) + Offset);2860assert(Offset == TotalSize);28612862// TODO: Implement direct writing to the output stream (without intermediate2863// memory buffer Buf).2864Out.write(Buf->getBufferStart(), Buf->getBufferSize());2865return Error::success();2866}28672868Error SRECSectionWriterBase::visit(const StringTableSection &Sec) {2869// Check that the sizer has already done its work.2870assert(Sec.Size == Sec.StrTabBuilder.getSize() &&2871"Expected section size to have been finalized");2872// We don't need to write anything here because the real writer has already2873// done it.2874return Error::success();2875}28762877Error SRECSectionWriterBase::visit(const Section &Sec) {2878writeSection(Sec, Sec.Contents);2879return Error::success();2880}28812882Error SRECSectionWriterBase::visit(const OwnedDataSection &Sec) {2883writeSection(Sec, Sec.Data);2884return Error::success();2885}28862887Error SRECSectionWriterBase::visit(const DynamicRelocationSection &Sec) {2888writeSection(Sec, Sec.Contents);2889return Error::success();2890}28912892void SRECSectionWriter::writeRecord(SRecord &Record, uint64_t Off) {2893SRecLineData Data = Record.toString();2894memcpy(Out.getBufferStart() + Off, Data.data(), Data.size());2895}28962897void SRECSectionWriterBase::writeRecords(uint32_t Entry) {2898// The ELF header could contain an entry point outside of the sections we have2899// seen that does not fit the current record Type.2900Type = std::max(Type, SRecord::getType(Entry));2901uint64_t Off = HeaderSize;2902for (SRecord &Record : Records) {2903Record.Type = Type;2904writeRecord(Record, Off);2905Off += Record.getSize();2906}2907Offset = Off;2908}29092910void SRECSectionWriterBase::writeSection(const SectionBase &S,2911ArrayRef<uint8_t> Data) {2912const uint32_t ChunkSize = 16;2913uint32_t Address = sectionPhysicalAddr(&S);2914uint32_t EndAddr = Address + S.Size - 1;2915Type = std::max(SRecord::getType(EndAddr), Type);2916while (!Data.empty()) {2917uint64_t DataSize = std::min<uint64_t>(Data.size(), ChunkSize);2918SRecord Record{Type, Address, Data.take_front(DataSize)};2919Records.push_back(Record);2920Data = Data.drop_front(DataSize);2921Address += DataSize;2922}2923}29242925Error SRECSectionWriter::visit(const StringTableSection &Sec) {2926assert(Sec.Size == Sec.StrTabBuilder.getSize() &&2927"Section size does not match the section's string table builder size");2928std::vector<uint8_t> Data(Sec.Size);2929Sec.StrTabBuilder.write(Data.data());2930writeSection(Sec, Data);2931return Error::success();2932}29332934SRecLineData SRecord::toString() const {2935SRecLineData Line(getSize());2936auto *Iter = Line.begin();2937*Iter++ = 'S';2938*Iter++ = '0' + Type;2939// Write 1 byte (2 hex characters) record count.2940Iter = toHexStr(getCount(), Iter, 2);2941// Write the address field with length depending on record type.2942Iter = toHexStr(Address, Iter, getAddressSize());2943// Write data byte by byte.2944for (uint8_t X : Data)2945Iter = toHexStr(X, Iter, 2);2946// Write the 1 byte checksum.2947Iter = toHexStr(getChecksum(), Iter, 2);2948*Iter++ = '\r';2949*Iter++ = '\n';2950assert(Iter == Line.end());2951return Line;2952}29532954uint8_t SRecord::getChecksum() const {2955uint32_t Sum = getCount();2956Sum += (Address >> 24) & 0xFF;2957Sum += (Address >> 16) & 0xFF;2958Sum += (Address >> 8) & 0xFF;2959Sum += Address & 0xFF;2960for (uint8_t Byte : Data)2961Sum += Byte;2962return 0xFF - (Sum & 0xFF);2963}29642965size_t SRecord::getSize() const {2966// Type, Count, Checksum, and CRLF are two characters each.2967return 2 + 2 + getAddressSize() + Data.size() * 2 + 2 + 2;2968}29692970uint8_t SRecord::getAddressSize() const {2971switch (Type) {2972case Type::S2:2973return 6;2974case Type::S3:2975return 8;2976case Type::S7:2977return 8;2978case Type::S8:2979return 6;2980default:2981return 4;2982}2983}29842985uint8_t SRecord::getCount() const {2986uint8_t DataSize = Data.size();2987uint8_t ChecksumSize = 1;2988return getAddressSize() / 2 + DataSize + ChecksumSize;2989}29902991uint8_t SRecord::getType(uint32_t Address) {2992if (isUInt<16>(Address))2993return SRecord::S1;2994if (isUInt<24>(Address))2995return SRecord::S2;2996return SRecord::S3;2997}29982999SRecord SRecord::getHeader(StringRef FileName) {3000// Header is a record with Type S0, Address 0, and Data that is a3001// vendor-specific text comment. For the comment we will use the output file3002// name truncated to 40 characters to match the behavior of GNU objcopy.3003StringRef HeaderContents = FileName.slice(0, 40);3004ArrayRef<uint8_t> Data(3005reinterpret_cast<const uint8_t *>(HeaderContents.data()),3006HeaderContents.size());3007return {SRecord::S0, 0, Data};3008}30093010size_t SRECWriter::writeHeader(uint8_t *Buf) {3011SRecLineData Record = SRecord::getHeader(OutputFileName).toString();3012memcpy(Buf, Record.data(), Record.size());3013return Record.size();3014}30153016size_t SRECWriter::writeTerminator(uint8_t *Buf, uint8_t Type) {3017assert(Type >= SRecord::S7 && Type <= SRecord::S9 &&3018"Invalid record type for terminator");3019uint32_t Entry = Obj.Entry;3020SRecLineData Data = SRecord{Type, Entry, {}}.toString();3021memcpy(Buf, Data.data(), Data.size());3022return Data.size();3023}30243025Expected<size_t>3026SRECWriter::getTotalSize(WritableMemoryBuffer &EmptyBuffer) const {3027SRECSizeCalculator SizeCalc(EmptyBuffer, 0);3028for (const SectionBase *Sec : Sections)3029if (Error Err = Sec->accept(SizeCalc))3030return std::move(Err);30313032SizeCalc.writeRecords(Obj.Entry);3033// We need to add the size of the Header and Terminator records.3034SRecord Header = SRecord::getHeader(OutputFileName);3035uint8_t TerminatorType = 10 - SizeCalc.getType();3036SRecord Terminator = {TerminatorType, static_cast<uint32_t>(Obj.Entry), {}};3037return Header.getSize() + SizeCalc.getBufferOffset() + Terminator.getSize();3038}30393040Error SRECWriter::write() {3041uint32_t HeaderSize =3042writeHeader(reinterpret_cast<uint8_t *>(Buf->getBufferStart()));3043SRECSectionWriter Writer(*Buf, HeaderSize);3044for (const SectionBase *S : Sections) {3045if (Error E = S->accept(Writer))3046return E;3047}3048Writer.writeRecords(Obj.Entry);3049uint64_t Offset = Writer.getBufferOffset();30503051// An S1 record terminates with an S9 record, S2 with S8, and S3 with S7.3052uint8_t TerminatorType = 10 - Writer.getType();3053Offset += writeTerminator(3054reinterpret_cast<uint8_t *>(Buf->getBufferStart() + Offset),3055TerminatorType);3056assert(Offset == TotalSize);3057Out.write(Buf->getBufferStart(), Buf->getBufferSize());3058return Error::success();3059}30603061namespace llvm {3062namespace objcopy {3063namespace elf {30643065template class ELFBuilder<ELF64LE>;3066template class ELFBuilder<ELF64BE>;3067template class ELFBuilder<ELF32LE>;3068template class ELFBuilder<ELF32BE>;30693070template class ELFWriter<ELF64LE>;3071template class ELFWriter<ELF64BE>;3072template class ELFWriter<ELF32LE>;3073template class ELFWriter<ELF32BE>;30743075} // end namespace elf3076} // end namespace objcopy3077} // end namespace llvm307830793080