29#include <unordered_set>
40 uint8_t *
B =
reinterpret_cast<uint8_t *
>(Buf->getBufferStart()) +
41 Obj.ProgramHdrSegment.Offset + Seg.
Index *
sizeof(Elf_Phdr);
42 Elf_Phdr &Phdr = *
reinterpret_cast<Elf_Phdr *
>(
B);
43 Phdr.p_type = Seg.
Type;
44 Phdr.p_flags = Seg.
Flags;
45 Phdr.p_offset = Seg.
Offset;
46 Phdr.p_vaddr = Seg.
VAddr;
47 Phdr.p_paddr = Seg.
PAddr;
50 Phdr.p_align = Seg.
Align;
71 reinterpret_cast<uint8_t *
>(Buf->getBufferStart()) + Sec.
HeaderOffset;
72 Elf_Shdr &
Shdr = *
reinterpret_cast<Elf_Shdr *
>(
B);
107 Sec.
Align = ELFT::Is64Bits ?
sizeof(Elf_Xword) :
sizeof(Elf_Word);
113 using uint = std::conditional_t<Is64, uint64_t, uint32_t>;
116 ELF::encodeCrel<Is64>(
OS, Relocations, [&](
const Relocation &R) {
117 uint32_t CurSymIdx = R.RelocSymbol ? R.RelocSymbol->Index : 0;
119 std::make_signed_t<uint>(R.Addend)};
127 Sec.
Size = encodeCrel<ELFT::Is64Bits>(Sec.Relocations).size();
132 Sec.
Align = ELFT::Is64Bits ?
sizeof(Elf_Xword) :
sizeof(Elf_Word);
143 Sec.
Size =
sizeof(Elf_Word) + Sec.GroupMembers.size() *
sizeof(Elf_Word);
163 "cannot write symbol section index table '" +
169 "cannot write symbol table '" + Sec.
Name +
175 "cannot write relocation section '" + Sec.
Name +
181 "cannot write '" + Sec.
Name +
"' out to binary");
186 "cannot write '" + Sec.
Name +
"' out to binary");
198 return Addr > UINT32_MAX &&
Addr + 0x80000000 > UINT32_MAX;
211template <
class T,
class Iterator>
214 std::fill(It, It + Len,
'0');
216 for (
long I = Len - 1;
I >= 0; --
I) {
217 unsigned char Mod =
static_cast<unsigned char>(
X) & 15;
218 *(It +
I) = hexdigit(
Mod,
false);
227 uint8_t Checksum = 0;
229 Checksum += checkedGetHex<uint8_t>(S.
take_front(2));
239 auto Iter = Line.begin();
244 for (uint8_t
X :
Data)
246 StringRef S(Line.data() + 1, std::distance(Line.begin() + 1, Iter));
250 assert(Iter == Line.end());
257 if (R.HexData.size() == 0)
260 "zero data length is not allowed for data records");
267 if (R.HexData.size() != 4)
270 "segment address data should be 2 bytes in size");
274 if (R.HexData.size() != 8)
276 "start address data should be 4 bytes in size");
282 R.HexData.take_front(3) !=
"000")
284 "start address exceeds 20 bit for 80x86");
288 if (R.HexData.size() != 4)
291 "extended address data should be 2 bytes in size");
296 static_cast<unsigned>(R.Type));
308 "missing ':' in the beginning of line.");
310 for (
size_t Pos = 1; Pos < Line.size(); ++Pos)
311 if (hexDigitValue(Line[Pos]) == -1U)
313 "invalid character at position %zu.", Pos + 1);
321 if (Line.size() < 11)
323 "line is too short: %zu chars.", Line.size());
329 size_t DataLen = checkedGetHex<uint8_t>(Line.substr(1, 2));
332 "invalid line length %zu (should be %zu)",
335 Rec.
Addr = checkedGetHex<uint16_t>(Line.substr(3, 4));
336 Rec.
Type = checkedGetHex<uint8_t>(Line.substr(7, 2));
337 Rec.
HexData = Line.substr(9, DataLen * 2);
359 while (!
Data.empty()) {
360 uint64_t DataSize = std::min<uint64_t>(
Data.size(), ChunkSize);
361 if (
Addr > SegmentAddr + BaseAddr + 0xFFFFU) {
362 if (
Addr > 0xFFFFFU) {
365 if (SegmentAddr != 0)
366 SegmentAddr = writeSegmentAddr(0U);
367 BaseAddr = writeBaseAddr(
Addr);
370 SegmentAddr = writeSegmentAddr(
Addr);
374 assert(SegOffset <= 0xFFFFU);
375 DataSize = std::min(DataSize, 0x10000U - SegOffset);
384 uint8_t
Data[] = {
static_cast<uint8_t
>((
Addr & 0xF0000U) >> 12), 0};
386 return Addr & 0xF0000U;
392 uint8_t
Data[] = {
static_cast<uint8_t
>(
Base >> 24),
393 static_cast<uint8_t
>((
Base >> 16) & 0xFF)};
437 std::vector<uint8_t>
Data(Sec.
Size);
444 return Visitor.
visit(*
this);
448 return Visitor.
visit(*
this);
453 assert(LinkSection ==
nullptr);
454 LinkSection = &SymTab;
478 "--decompress-debug-sections: ch_type (" +
480 Sec.
Name +
"' is unsupported");
485 "failed to decompress section '" + Sec.
Name +
488 static_cast<size_t>(Sec.
Size)))
490 "failed to decompress section '" + Sec.
Name +
493 uint8_t *Buf =
reinterpret_cast<uint8_t *
>(Out.getBufferStart()) + Sec.
Offset;
494 std::copy(Decompressed.
begin(), Decompressed.
end(), Buf);
501 "cannot write compressed section '" + Sec.
Name +
506 return Visitor.
visit(*
this);
510 return Visitor.
visit(*
this);
514 return Visitor.
visit(*
this);
518 return Visitor.
visit(*
this);
523 while (!HexData.
empty()) {
524 Data.push_back(checkedGetHex<uint8_t>(HexData.
take_front(2)));
532 "cannot write compressed section '" + Sec.
Name +
538 uint8_t *Buf =
reinterpret_cast<uint8_t *
>(Out.getBufferStart()) + Sec.
Offset;
540 switch (Sec.CompressionType) {
551 Chdr.ch_size = Sec.DecompressedSize;
552 Chdr.ch_addralign = Sec.DecompressedAlign;
553 memcpy(Buf, &Chdr,
sizeof(Chdr));
556 std::copy(Sec.CompressedData.begin(), Sec.CompressedData.end(), Buf);
563 :
SectionBase(Sec), CompressionType(CompressionType),
564 DecompressedSize(Sec.OriginalData.
size()), DecompressedAlign(Sec.
Align) {
572 Size = ChdrSize + CompressedData.
size();
580 DecompressedSize(DecompressedSize), DecompressedAlign(DecompressedAlign) {
585 return Visitor.
visit(*
this);
589 return Visitor.
visit(*
this);
610 return Visitor.
visit(*
this);
614 return Visitor.
visit(*
this);
619 uint8_t *Buf =
reinterpret_cast<uint8_t *
>(Out.getBufferStart()) + Sec.
Offset;
620 llvm::copy(Sec.Indexes,
reinterpret_cast<Elf_Word *
>(Buf));
632 " is not a symbol table");
644 return Visitor.
visit(*
this);
648 return Visitor.
visit(*
this);
708void SymbolTableSection::assignIndices() {
725 Sym.DefinedIn = DefinedIn;
726 if (DefinedIn !=
nullptr)
728 if (DefinedIn ==
nullptr) {
735 Sym.Visibility = Visibility;
736 Sym.Size = SymbolSize;
738 Symbols.emplace_back(std::make_unique<Symbol>(
Sym));
747 if (!AllowBrokenLinks)
750 "string table '%s' cannot be removed because it is "
751 "referenced by the symbol table '%s'",
762 std::stable_partition(
774 auto PrevSize =
Size;
794 "Symbol table has link index of " +
Twine(
Link) +
795 " which is not a valid index",
796 "Symbol table has link index of " +
Twine(
Link) +
797 " which is not a string table");
807 for (std::unique_ptr<Symbol> &
Sym :
Symbols) {
811 MaxLocalIndex = std::max(MaxLocalIndex,
Sym->Index);
815 Info = MaxLocalIndex + 1;
839 for (
const std::unique_ptr<Symbol> &
Sym :
Symbols) {
859 return Sym.takeError();
861 return const_cast<Symbol *
>(*Sym);
866 Elf_Sym *
Sym =
reinterpret_cast<Elf_Sym *
>(Out.getBufferStart() + Sec.
Offset);
882 return Visitor.
visit(*
this);
886 return Visitor.
visit(*
this);
905 if (!AllowBrokenLinks)
908 "symbol table '%s' cannot be removed because it is "
909 "referenced by the relocation section '%s'",
915 if (!R.RelocSymbol || !R.RelocSymbol->DefinedIn ||
916 !
ToRemove(R.RelocSymbol->DefinedIn))
919 "section '%s' cannot be removed: (%s+0x%" PRIx64
920 ") has relocation against symbol '%s'",
921 R.RelocSymbol->DefinedIn->Name.data(),
923 R.RelocSymbol->Name.c_str());
929template <
class SymTabType>
935 "Link field value " +
Twine(Link) +
" in section " +
Name +
937 "Link field value " +
Twine(Link) +
" in section " +
Name +
938 " is not a symbol table");
948 " in section " +
Name +
" is invalid");
959template <
class SymTabType>
961 this->Link = Symbols ? Symbols->Index : 0;
963 if (SecToApplyRel !=
nullptr)
964 this->
Info = SecToApplyRel->Index;
972 Rela.r_addend = Addend;
975template <
class RelRange,
class T>
976static void writeRel(
const RelRange &Relocations,
T *Buf,
bool IsMips64EL) {
977 for (
const auto &Reloc : Relocations) {
978 Buf->r_offset = Reloc.Offset;
980 Buf->setSymbolAndType(Reloc.RelocSymbol ? Reloc.RelocSymbol->Index : 0,
981 Reloc.Type, IsMips64EL);
988 uint8_t *Buf =
reinterpret_cast<uint8_t *
>(Out.getBufferStart()) + Sec.
Offset;
990 auto Content = encodeCrel<ELFT::Is64Bits>(Sec.Relocations);
993 writeRel(Sec.Relocations,
reinterpret_cast<Elf_Rel *
>(Buf),
996 writeRel(Sec.Relocations,
reinterpret_cast<Elf_Rela *
>(Buf),
1003 return Visitor.
visit(*
this);
1007 return Visitor.
visit(*
this);
1013 if (Reloc.RelocSymbol &&
ToRemove(*Reloc.RelocSymbol))
1016 "not stripping symbol '%s' because it is named in a relocation",
1017 Reloc.RelocSymbol->Name.data());
1023 if (Reloc.RelocSymbol)
1024 Reloc.RelocSymbol->Referenced =
true;
1040 return Visitor.
visit(*
this);
1044 return Visitor.
visit(*
this);
1050 if (!AllowBrokenLinks)
1053 "symbol table '%s' cannot be removed because it is "
1054 "referenced by the relocation section '%s'",
1068 bool AllowBrokenDependency,
1071 if (!AllowBrokenDependency)
1073 "section '%s' cannot be removed because it is "
1074 "referenced by the section '%s'",
1075 LinkSection->
Name.data(), this->Name.data());
1076 LinkSection =
nullptr;
1083 this->
Link = SymTab ? SymTab->
Index : 0;
1089 this->FlagWord &= ~GRP_COMDAT;
1095 if (!AllowBrokenLinks)
1098 "section '.symtab' cannot be removed because it is "
1099 "referenced by the group section '%s'",
1111 "symbol '%s' cannot be removed because it is "
1112 "referenced by the section '%s[%d]'",
1113 Sym->
Name.data(), this->Name.data(), this->Index);
1133 Sec->
Flags &= ~SHF_GROUP;
1142 " in section " +
Name +
" is invalid");
1149 HasSymTabLink =
true;
1150 LinkSection =
nullptr;
1168 Name =
".gnu_debuglink";
1177 : FileName(
File), CRC32(PrecomputedCRC) {
1181template <
class ELFT>
1183 unsigned char *Buf =
1184 reinterpret_cast<uint8_t *
>(Out.getBufferStart()) + Sec.
Offset;
1186 reinterpret_cast<Elf_Word *
>(Buf + Sec.
Size -
sizeof(Elf_Word));
1193 return Visitor.
visit(*
this);
1197 return Visitor.
visit(*
this);
1200template <
class ELFT>
1204 endian::write32<ELFT::Endianness>(Buf++, Sec.FlagWord);
1206 endian::write32<ELFT::Endianness>(Buf++, S->
Index);
1211 return Visitor.
visit(*
this);
1215 return Visitor.
visit(*
this);
1236 if (SectionIsTLS != SegmentIsTLS)
1259 if (
A->OriginalOffset <
B->OriginalOffset)
1261 if (
A->OriginalOffset >
B->OriginalOffset)
1267 if (
A->Align !=
B->Align)
1268 return A->Align >
B->Align;
1269 return A->Index <
B->Index;
1276 Obj->ABIVersion = 0;
1286 StrTab.
Name =
".strtab";
1288 Obj->SectionNames = &StrTab;
1295 SymTab.
Name =
".symtab";
1296 SymTab.Link = StrTab->
Index;
1299 SymTab.addSymbol(
"", 0, 0,
nullptr, 0, 0, 0, 0);
1301 Obj->SymbolTable = &SymTab;
1318 DataSection.
Name =
".data";
1320 DataSection.Size =
Data.size();
1325 std::begin(SanitizedFilename), std::end(SanitizedFilename),
1326 [](
char C) {
return !isAlnum(
C); },
'_');
1327 Twine Prefix =
Twine(
"_binary_") + SanitizedFilename;
1330 0, NewSymbolVisibility, 0, 0);
1332 DataSection.Size, NewSymbolVisibility, 0, 0);
1334 DataSection.Size, NewSymbolVisibility,
SHN_ABS,
1344 return std::move(Err);
1347 return std::move(
Obj);
1352void IHexELFBuilder::addDataSections() {
1354 uint64_t SegmentAddr = 0, BaseAddr = 0;
1362 if (R.HexData.empty())
1364 RecAddr = R.Addr + SegmentAddr + BaseAddr;
1371 ".sec" + std::to_string(SecNo), RecAddr,
1375 Section->appendHexData(R.HexData);
1381 SegmentAddr = checkedGetHex<uint16_t>(R.HexData) << 4;
1385 Obj->Entry = checkedGetHex<uint32_t>(R.HexData);
1390 BaseAddr = checkedGetHex<uint16_t>(R.HexData) << 16;
1404 return std::move(Err);
1407 return std::move(
Obj);
1410template <
class ELFT>
1412 std::optional<StringRef> ExtractPartition)
1413 : ElfFile(ElfObj.getELFFile()), Obj(Obj),
1414 ExtractPartition(ExtractPartition) {
1419 for (
Segment &Parent : Obj.segments()) {
1435 if (!ExtractPartition)
1445 "could not find partition named '" +
1446 *ExtractPartition +
"'");
1449template <
class ELFT>
1459 if (Phdr.p_offset + Phdr.p_filesz > HeadersFile.
getBufSize())
1464 " goes past the end of the file");
1467 (size_t)Phdr.p_filesz};
1469 Seg.
Type = Phdr.p_type;
1470 Seg.
Flags = Phdr.p_flags;
1472 Seg.
Offset = Phdr.p_offset + EhdrOffset;
1473 Seg.
VAddr = Phdr.p_vaddr;
1474 Seg.
PAddr = Phdr.p_paddr;
1477 Seg.
Align = Phdr.p_align;
1487 auto &ElfHdr = Obj.ElfHdrSegment;
1489 ElfHdr.OriginalOffset = ElfHdr.Offset = EhdrOffset;
1491 const typename ELFT::Ehdr &Ehdr = HeadersFile.
getHeader();
1492 auto &PrHdr = Obj.ProgramHdrSegment;
1499 PrHdr.OriginalOffset = PrHdr.Offset = PrHdr.VAddr = EhdrOffset + Ehdr.e_phoff;
1501 PrHdr.FileSize = PrHdr.MemSize = Ehdr.e_phentsize * Ehdr.e_phnum;
1503 PrHdr.Align =
sizeof(Elf_Addr);
1504 PrHdr.Index =
Index++;
1508 for (
Segment &Child : Obj.segments())
1509 setParentSegment(Child);
1510 setParentSegment(ElfHdr);
1511 setParentSegment(PrHdr);
1516template <
class ELFT>
1520 "invalid alignment " +
Twine(GroupSec->
Align) +
1521 " of group section '" + GroupSec->
Name +
"'");
1524 auto SymTab = SecTable.template getSectionOfType<SymbolTableSection>(
1526 "link field value '" +
Twine(GroupSec->
Link) +
"' in section '" +
1527 GroupSec->
Name +
"' is invalid",
1528 "link field value '" +
Twine(GroupSec->
Link) +
"' in section '" +
1529 GroupSec->
Name +
"' is not a symbol table");
1531 return SymTab.takeError();
1536 "info field value '" +
Twine(GroupSec->
Info) +
1537 "' in section '" + GroupSec->
Name +
1538 "' is not a valid symbol index");
1545 "the content of the section " + GroupSec->
Name +
1551 GroupSec->
setFlagWord(endian::read32<ELFT::Endianness>(Word++));
1553 uint32_t Index = support::endian::read32<ELFT::Endianness>(Word);
1556 GroupSec->
Name +
"' is invalid");
1566template <
class ELFT>
1570 return Shdr.takeError();
1579 ElfFile.symbols(*
Shdr);
1581 return Symbols.takeError();
1588 return Name.takeError();
1593 "symbol '" + *
Name +
1594 "' has index SHN_XINDEX but no "
1595 "SHT_SYMTAB_SHNDX section exists");
1596 if (ShndxData.
data() ==
nullptr) {
1603 ElfFile.template getSectionContentsAsArray<Elf_Word>(**ShndxSec);
1605 return Data.takeError();
1608 if (ShndxData.
size() != Symbols->size())
1611 "symbol section index table does not have the same number of "
1612 "entries as the symbol table");
1614 Elf_Word
Index = ShndxData[&
Sym - Symbols->begin()];
1617 "symbol '" + *
Name +
"' has invalid section index " +
Twine(
Index));
1626 "symbol '" + *
Name +
1627 "' has unsupported value greater than or equal "
1628 "to SHN_LORESERVE: " +
1633 Sym.st_shndx,
"symbol '" + *
Name +
1634 "' is defined has invalid section index " +
1643 Sym.getValue(),
Sym.st_other,
Sym.st_shndx,
Sym.st_size);
1649template <
class ELFT>
1652template <
class ELFT>
1654 ToSet = Rela.r_addend;
1659 for (
const auto &Rel : RelRange) {
1661 ToAdd.
Offset = Rel.r_offset;
1669 "'" + Relocs->
Name +
"': relocation references symbol with index " +
1670 Twine(
Sym) +
", but there is no symbol table");
1689 return Sections[
Index - 1].get();
1700 if (
T *Sec = dyn_cast<T>(*BaseSec))
1706template <
class ELFT>
1708 switch (
Shdr.sh_type) {
1716 return Data.takeError();
1727 return Data.takeError();
1737 return Data.takeError();
1742 return Data.takeError();
1747 return Data.takeError();
1752 return Data.takeError();
1755 if (Obj.SymbolTable !=
nullptr)
1757 "found multiple SHT_SYMTAB sections");
1759 Obj.SymbolTable = &SymTab;
1764 Obj.SectionIndexTable = &ShndxSection;
1765 return ShndxSection;
1772 return Data.takeError();
1776 return Name.takeError();
1782 *
Data, Chdr->ch_type, Chdr->ch_size, Chdr->ch_addralign));
1806 Sec->Name = SecName->str();
1807 Sec->Type = Sec->OriginalType =
Shdr.sh_type;
1808 Sec->Flags = Sec->OriginalFlags =
Shdr.sh_flags;
1809 Sec->Addr =
Shdr.sh_addr;
1810 Sec->Offset =
Shdr.sh_offset;
1811 Sec->OriginalOffset =
Shdr.sh_offset;
1812 Sec->Size =
Shdr.sh_size;
1813 Sec->Link =
Shdr.sh_link;
1814 Sec->Info =
Shdr.sh_info;
1815 Sec->Align =
Shdr.sh_addralign;
1816 Sec->EntrySize =
Shdr.sh_entsize;
1817 Sec->Index =
Index++;
1818 Sec->OriginalIndex = Sec->Index;
1820 ElfFile.base() +
Shdr.sh_offset,
1828 uint32_t ShstrIndex = ElfFile.getHeader().e_shstrndx;
1834 ShstrIndex = (*Sec)->sh_link;
1838 Obj.HadShdrs =
false;
1841 Obj.sections().template getSectionOfType<StringTableSection>(
1843 "e_shstrndx field value " +
Twine(ShstrIndex) +
" in elf header " +
1845 "e_shstrndx field value " +
Twine(ShstrIndex) +
" in elf header " +
1846 " does not reference a string table");
1850 Obj.SectionNames = *Sec;
1856 if (Obj.SectionIndexTable)
1857 if (
Error Err = Obj.SectionIndexTable->initialize(Obj.sections()))
1863 if (Obj.SymbolTable) {
1864 if (
Error Err = Obj.SymbolTable->initialize(Obj.sections()))
1866 if (
Error Err = initSymbolTable(Obj.SymbolTable))
1868 }
else if (EnsureSymtab) {
1869 if (
Error Err = Obj.addNewSymbolTable())
1877 if (&Sec == Obj.SymbolTable)
1879 if (
Error Err = Sec.initialize(Obj.sections()))
1881 if (
auto RelSec = dyn_cast<RelocationSection>(&Sec)) {
1888 Sections->begin() + RelSec->Index;
1890 auto RelsOrRelas = ElfFile.crels(*
Shdr);
1892 return RelsOrRelas.takeError();
1897 }
else if (RelSec->Type ==
SHT_REL) {
1899 ElfFile.rels(*
Shdr);
1907 ElfFile.relas(*
Shdr);
1914 }
else if (
auto GroupSec = dyn_cast<GroupSection>(&Sec)) {
1915 if (
Error Err = initGroupSection(GroupSec))
1924 if (
Error E = readSectionHeaders())
1926 if (
Error E = findEhdrOffset())
1933 {ElfFile.base() + EhdrOffset, ElfFile.getBufSize() - EhdrOffset}));
1939 Obj.OSABI = Ehdr.e_ident[
EI_OSABI];
1941 Obj.Type = Ehdr.e_type;
1942 Obj.Machine = Ehdr.e_machine;
1943 Obj.Version = Ehdr.e_version;
1944 Obj.Entry = Ehdr.e_entry;
1945 Obj.Flags = Ehdr.e_flags;
1947 if (
Error E = readSections(EnsureSymtab))
1949 return readProgramHeaders(*HeadersFile);
1963 std::vector<IHexRecord> Records;
1964 bool HasSections =
false;
1967 Records.reserve(Lines.size());
1968 for (
size_t LineNo = 1; LineNo <= Lines.size(); ++LineNo) {
1969 StringRef Line = Lines[LineNo - 1].trim();
1975 return parseError(LineNo, R.takeError());
1979 Records.push_back(*R);
1982 return parseError(-1U,
"no sections");
1984 return std::move(Records);
1991 return Records.takeError();
1997 auto Obj = std::make_unique<Object>();
2001 return std::move(Err);
2002 return std::move(Obj);
2006 return std::move(Err);
2007 return std::move(Obj);
2011 return std::move(Err);
2012 return std::move(Obj);
2016 return std::move(Err);
2017 return std::move(Obj);
2023 Elf_Ehdr &Ehdr = *
reinterpret_cast<Elf_Ehdr *
>(Buf->getBufferStart());
2024 std::fill(Ehdr.e_ident, Ehdr.e_ident + 16, 0);
2033 Ehdr.e_ident[
EI_OSABI] = Obj.OSABI;
2036 Ehdr.e_type = Obj.Type;
2037 Ehdr.e_machine = Obj.Machine;
2038 Ehdr.e_version = Obj.Version;
2039 Ehdr.e_entry = Obj.Entry;
2043 Ehdr.e_phoff = (Ehdr.e_phnum != 0) ? Obj.ProgramHdrSegment.Offset : 0;
2044 Ehdr.e_phentsize = (Ehdr.e_phnum != 0) ?
sizeof(Elf_Phdr) : 0;
2045 Ehdr.e_flags = Obj.Flags;
2046 Ehdr.e_ehsize =
sizeof(Elf_Ehdr);
2047 if (WriteSectionHeaders && Obj.sections().size() != 0) {
2048 Ehdr.e_shentsize =
sizeof(Elf_Shdr);
2049 Ehdr.e_shoff = Obj.SHOff;
2056 auto Shnum = Obj.sections().size() + 1;
2060 Ehdr.e_shnum = Shnum;
2070 Ehdr.e_shstrndx = Obj.SectionNames->Index;
2072 Ehdr.e_shentsize = 0;
2075 Ehdr.e_shstrndx = 0;
2080 for (
auto &Seg : Obj.segments())
2088 *
reinterpret_cast<Elf_Shdr *
>(Buf->getBufferStart() + Obj.SHOff);
2095 uint64_t Shnum = Obj.sections().size() + 1;
2097 Shdr.sh_size = Shnum;
2101 if (Obj.SectionNames !=
nullptr && Obj.SectionNames->Index >=
SHN_LORESERVE)
2102 Shdr.sh_link = Obj.SectionNames->Index;
2106 Shdr.sh_addralign = 0;
2107 Shdr.sh_entsize = 0;
2118 if (Sec.ParentSegment ==
nullptr)
2119 if (
Error Err = Sec.accept(*SecWriter))
2126 for (
Segment &Seg : Obj.segments()) {
2132 for (
const auto &it : Obj.getUpdatedSections()) {
2137 assert(Parent &&
"This section should've been part of a segment.");
2144 for (
auto &Sec : Obj.removedSections()) {
2145 Segment *Parent = Sec.ParentSegment;
2146 if (Parent ==
nullptr || Sec.Type ==
SHT_NOBITS || Sec.Size == 0)
2150 std::memset(Buf->getBufferStart() +
Offset, 0, Sec.Size);
2154template <
class ELFT>
2157 :
Writer(Obj, Buf), WriteSectionHeaders(WSH && Obj.HadShdrs),
2158 OnlyKeepDebug(OnlyKeepDebug) {}
2162 [&](
const SecPtr &Sec) {
return Sec->Name ==
Name; });
2163 if (It == Sections.end())
2165 Name.str().c_str());
2167 auto *OldSec = It->get();
2168 if (!OldSec->hasContents())
2171 "section '%s' cannot be updated because it does not have contents",
2172 Name.str().c_str());
2174 if (
Data.size() > OldSec->Size && OldSec->ParentSegment)
2176 "cannot fit data of size %zu into section '%s' "
2177 "with size %" PRIu64
" that is part of a segment",
2178 Data.size(),
Name.str().c_str(), OldSec->Size);
2180 if (!OldSec->ParentSegment) {
2181 *It = std::make_unique<OwnedDataSection>(*OldSec,
Data);
2184 OldSec->Size =
Data.size();
2185 UpdatedSections[OldSec] =
Data;
2194 auto Iter = std::stable_partition(
2195 std::begin(Sections), std::end(Sections), [=](
const SecPtr &Sec) {
2200 if (isa<CompressedSection>(Sec))
2202 if (
auto RelSec = dyn_cast<RelocationSectionBase>(Sec.get())) {
2203 if (auto ToRelSec = RelSec->getSection())
2204 return !ToRemove(*ToRelSec);
2208 auto GroupSec = cast<GroupSection>(Sec.get());
2209 return !llvm::all_of(GroupSec->members(), ToRemove);
2222 std::unordered_set<const SectionBase *> RemoveSections;
2223 RemoveSections.
reserve(std::distance(Iter, std::end(Sections)));
2224 for (
auto &RemoveSec :
make_range(Iter, std::end(Sections))) {
2225 for (
auto &
Segment : Segments)
2227 RemoveSec->onRemove();
2228 RemoveSections.insert(RemoveSec.get());
2236 for (
auto &KeepSec :
make_range(std::begin(Sections), Iter)) {
2237 if (
Error E = KeepSec->removeSectionReferences(
2238 AllowBrokenLinks, [&RemoveSections](
const SectionBase *Sec) {
2239 return RemoveSections.find(Sec) != RemoveSections.end();
2246 std::move(Iter, Sections.end(), std::back_inserter(RemovedSections));
2248 Sections.erase(Iter, std::end(Sections));
2254 auto SectionIndexLess = [](
const SecPtr &Lhs,
const SecPtr &Rhs) {
2255 return Lhs->Index < Rhs->Index;
2258 "Sections are expected to be sorted by Index");
2261 for (
auto &
I : FromTo)
2262 I.second->Index =
I.first->Index;
2265 for (
auto &Sec : Sections)
2266 Sec->replaceSectionReferences(FromTo);
2278 for (
const SecPtr &Sec : Sections)
2300 StrTab = &addSection<StringTableSection>();
2303 SymTab.
Name =
".symtab";
2307 SymTab.
addSymbol(
"", 0, 0,
nullptr, 0, 0, 0, 0);
2330 for (
Segment *Seg : Segments) {
2354template <
class Range>
2364 std::vector<SectionBase *> OutOfSegmentSections;
2366 for (
auto &Sec : Sections) {
2367 Sec.Index =
Index++;
2368 if (Sec.ParentSegment !=
nullptr) {
2373 OutOfSegmentSections.push_back(&Sec);
2380 for (
auto *Sec : OutOfSegmentSections) {
2394 std::vector<SectionBase *> Sections;
2398 Sec.Index =
Index++;
2399 Sections.push_back(&Sec);
2406 for (
auto *Sec : Sections) {
2407 auto *FirstSec = Sec->ParentSegment && Sec->ParentSegment->Type ==
PT_LOAD
2408 ? Sec->ParentSegment->firstSection()
2413 if (FirstSec && FirstSec == Sec)
2414 Off =
alignTo(Off, Sec->ParentSegment->Align, Sec->Addr);
2427 Off = Sec->Align ?
alignTo(Off, Sec->Align) : Off;
2428 }
else if (FirstSec != Sec) {
2431 Off = Sec->OriginalOffset - FirstSec->OriginalOffset + FirstSec->Offset;
2444 for (
Segment *Seg : Segments) {
2456 FirstSec ? FirstSec->
Offset
2470 FileSize = std::max(FileSize, HdrEnd -
Offset);
2475 MaxOffset = std::max(MaxOffset,
Offset + FileSize);
2481 Segment &ElfHdr = Obj.ElfHdrSegment;
2494 std::vector<Segment *> OrderedSegments;
2496 OrderedSegments.push_back(&
Segment);
2497 OrderedSegments.push_back(&Obj.ElfHdrSegment);
2498 OrderedSegments.push_back(&Obj.ProgramHdrSegment);
2502 if (OnlyKeepDebug) {
2507 sizeof(Elf_Ehdr) +
llvm::size(Obj.segments()) *
sizeof(Elf_Phdr);
2520 if (WriteSectionHeaders)
2528 if (!WriteSectionHeaders)
2530 size_t ShdrCount = Obj.sections().size() + 1;
2531 return Obj.SHOff + ShdrCount *
sizeof(Elf_Shdr);
2540 if (
Error E = writeSectionData())
2542 if (WriteSectionHeaders)
2547 Out.write(Buf->getBufferStart(), Buf->getBufferSize());
2574 if (Obj.SectionNames ==
nullptr && WriteSectionHeaders)
2576 "cannot write section header table because "
2577 "section header string table was removed");
2584 if (Obj.SymbolTable && !Obj.SymbolTable->indicesChanged())
2586 Sec.restoreSymTabLink(*Obj.SymbolTable);
2591 bool NeedsLargeIndexes =
false;
2603 if (NeedsLargeIndexes) {
2606 if (Obj.SymbolTable !=
nullptr && Obj.SectionIndexTable ==
nullptr) {
2610 Obj.SymbolTable->setShndxTable(&Shndx);
2616 if (Obj.SectionIndexTable !=
nullptr) {
2618 if (
Error E = Obj.removeSections(
false ,
2620 return &Sec == Obj.SectionIndexTable;
2628 if (Obj.SectionNames !=
nullptr)
2630 Obj.SectionNames->addString(Sec.Name);
2638 auto SecSizer = std::make_unique<ELFSectionSizer<ELFT>>();
2640 Sec.Index =
Index++;
2641 if (
Error Err = Sec.accept(*SecSizer))
2648 if (Obj.SymbolTable !=
nullptr)
2649 Obj.SymbolTable->prepareForLayout();
2654 if (
auto StrTab = dyn_cast<StringTableSection>(&Sec))
2655 StrTab->prepareForLayout();
2661 if (Obj.SymbolTable !=
nullptr)
2662 Obj.SymbolTable->fillShndxTable();
2668 Sec.HeaderOffset =
Offset;
2669 Offset +=
sizeof(Elf_Shdr);
2670 if (WriteSectionHeaders)
2671 Sec.NameIndex = Obj.SectionNames->findIndex(Sec.Name);
2675 size_t TotalSize = totalSize();
2679 "failed to allocate memory buffer of " +
2682 SecWriter = std::make_unique<ELFSectionWriter<ELFT>>(*Buf);
2693 if (SectionsToWrite.
empty())
2698 return LHS->Offset <
RHS->Offset;
2703 for (
size_t i = 0; i != SectionsToWrite.
size(); ++i) {
2710 ? SectionsToWrite[i + 1]->
Offset
2711 :
Buf->getBufferSize();
2712 assert(PadOffset <= Buf->getBufferSize());
2715 Buf->getBufferStart() + PadOffset, GapFill);
2731 if (Sec.ParentSegment !=
nullptr)
2733 Sec.Offset - Sec.ParentSegment->Offset + Sec.ParentSegment->PAddr;
2735 MinAddr = std::min(MinAddr, Sec.Addr);
2742 TotalSize = PadTo > MinAddr ? PadTo - MinAddr : 0;
2744 if (Sec.Type !=
SHT_NOBITS && Sec.Size > 0) {
2745 Sec.Offset = Sec.Addr - MinAddr;
2746 TotalSize = std::max(TotalSize, Sec.Offset + Sec.Size);
2752 "failed to allocate memory buffer of " +
2754 SecWriter = std::make_unique<BinarySectionWriter>(*
Buf);
2763 "section '%s' address range [0x%llx, 0x%llx] is not 32 bit",
2772 "entry point address 0x%llx overflows 32 bits",
2787 std::unique_ptr<WritableMemoryBuffer> EmptyBuffer =
2791 "failed to allocate memory buffer of 0 bytes");
2801 "failed to allocate memory buffer of 0x" +
2806uint64_t IHexWriter::writeEntryPointRecord(uint8_t *Buf) {
2808 uint8_t
Data[4] = {};
2824 return HexData.
size();
2827uint64_t IHexWriter::writeEndOfFileRecord(uint8_t *Buf) {
2830 return HexData.
size();
2837 if (
Error Err = Sec->accept(LengthCalc))
2838 return std::move(Err);
2842 return LengthCalc.getBufferOffset() +
2856 Offset += writeEntryPointRecord(
2857 reinterpret_cast<uint8_t *
>(
Buf->getBufferStart()) +
Offset);
2859 Offset += writeEndOfFileRecord(
2860 reinterpret_cast<uint8_t *
>(
Buf->getBufferStart()) +
Offset);
2872 "Expected section size to have been finalized");
2917 while (!
Data.empty()) {
2918 uint64_t DataSize = std::min<uint64_t>(
Data.size(), ChunkSize);
2928 "Section size does not match the section's string table builder size");
2929 std::vector<uint8_t>
Data(Sec.
Size);
2937 auto *Iter = Line.begin();
2939 *Iter++ =
'0' +
Type;
2945 for (uint8_t
X :
Data)
2951 assert(Iter == Line.end());
2957 Sum += (
Address >> 24) & 0xFF;
2958 Sum += (
Address >> 16) & 0xFF;
2961 for (uint8_t Byte :
Data)
2963 return 0xFF - (Sum & 0xFF);
2988 uint8_t ChecksumSize = 1;
3006 reinterpret_cast<const uint8_t *
>(HeaderContents.
data()),
3007 HeaderContents.
size());
3011size_t SRECWriter::writeHeader(uint8_t *Buf) {
3017size_t SRECWriter::writeTerminator(uint8_t *Buf, uint8_t
Type) {
3019 "Invalid record type for terminator");
3030 if (
Error Err = Sec->accept(SizeCalc))
3031 return std::move(Err);
3036 uint8_t TerminatorType = 10 - SizeCalc.getType();
3038 return Header.getSize() + SizeCalc.getBufferOffset() +
Terminator.getSize();
3043 writeHeader(
reinterpret_cast<uint8_t *
>(
Buf->getBufferStart()));
3053 uint8_t TerminatorType = 10 -
Writer.getType();
3054 Offset += writeTerminator(
3055 reinterpret_cast<uint8_t *
>(
Buf->getBufferStart() +
Offset),
ReachingDefAnalysis InstSet & ToRemove
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
COFF::MachineTypes Machine
Analysis containing CSE Info
static bool segmentOverlapsSegment(const Segment &Child, const Segment &Parent)
static void setAddend(Elf_Rel_Impl< ELFT, false > &, uint64_t)
static Error checkChars(StringRef Line)
static void orderSegments(std::vector< Segment * > &Segments)
static uint64_t layoutSegments(std::vector< Segment * > &Segments, uint64_t Offset)
static bool compareSegmentsByOffset(const Segment *A, const Segment *B)
static uint64_t layoutSections(Range Sections, uint64_t Offset)
static uint64_t layoutSectionsForOnlyKeepDebug(Object &Obj, uint64_t Off)
static bool isValidReservedSectionIndex(uint16_t Index, uint16_t Machine)
static uint64_t layoutSegmentsForOnlyKeepDebug(std::vector< Segment * > &Segments, uint64_t HdrEnd)
static void getAddend(uint64_t &, const Elf_Rel_Impl< ELFT, false > &)
static void writeRel(const RelRange &Relocations, T *Buf, bool IsMips64EL)
static bool addressOverflows32bit(uint64_t Addr)
static T checkedGetHex(StringRef S)
static uint64_t sectionPhysicalAddr(const SectionBase *Sec)
static Iterator toHexStr(T X, Iterator It, size_t Len)
static Error checkRecord(const IHexRecord &R)
static Error initRelocations(RelocationSection *Relocs, T RelRange)
static Error removeUnneededSections(Object &Obj)
static bool sectionWithinSegment(const SectionBase &Sec, const Segment &Seg)
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
bool empty() const
empty - Check if the array is empty.
ArrayRef< T > slice(size_t N, size_t M) const
slice(n, m) - Chop off the first N elements of the array, and keep M elements in the array.
ValueT lookup(const_arg_type_t< KeyT > Val) const
lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
Error takeError()
Take ownership of the stored error.
virtual StringRef getBufferIdentifier() const
Return an identifier for this buffer, typically the filename it was read from.
size_t getBufferSize() const
StringRef getBuffer() const
const char * getBufferStart() const
void push_back(const T &Elt)
pointer data()
Return a pointer to the vector's buffer, even if empty().
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
bool getAsInteger(unsigned Radix, T &Result) const
Parse the current string as an integer of the specified radix.
std::string str() const
str - Get the contents as an std::string.
constexpr bool empty() const
empty - Check if the string is empty.
StringRef drop_front(size_t N=1) const
Return a StringRef equal to 'this' but with the first N elements dropped.
StringRef slice(size_t Start, size_t End) const
Return a reference to the substring from [Start, End).
constexpr size_t size() const
size - Get the string size.
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
StringRef take_front(size_t N=1) const
Return a StringRef equal to 'this' but with only the first N elements remaining.
size_t getOffset(CachedHashStringRef S) const
Get the offest of a string in the string table.
void write(raw_ostream &OS) const
size_t add(CachedHashStringRef S)
Add a string to the builder.
void finalize()
Analyze the strings and build the final table.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
static Twine utohexstr(const uint64_t &Val)
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM Value Representation.
This class is an extension of MemoryBuffer, which allows copy-on-write access to the underlying conte...
static std::unique_ptr< WritableMemoryBuffer > getNewMemBuffer(size_t Size, const Twine &BufferName="")
Allocate a new zero-initialized MemoryBuffer of the specified size.
An efficient, type-erasing, non-owning reference to a callable.
Error checkSection(const SectionBase &S) const
Error finalize() override
std::vector< const SectionBase * > Sections
virtual Expected< size_t > getTotalSize(WritableMemoryBuffer &EmptyBuffer) const =0
StringTableSection * addStrTab()
SymbolTableSection * addSymTab(StringTableSection *StrTab)
std::unique_ptr< Object > Obj
Expected< std::unique_ptr< Object > > build()
Expected< std::unique_ptr< Object > > create(bool EnsureSymtab) const override
Error visit(const SymbolTableSection &Sec) override
Error finalize() override
Error accept(SectionVisitor &Visitor) const override
CompressedSection(const SectionBase &Sec, DebugCompressionType CompressionType, bool Is64Bits)
Error accept(SectionVisitor &Visitor) const override
Error accept(SectionVisitor &) const override
Error removeSectionReferences(bool AllowBrokenLinks, function_ref< bool(const SectionBase *)> ToRemove) override
ELFBuilder(const ELFObjectFile< ELFT > &ElfObj, Object &Obj, std::optional< StringRef > ExtractPartition)
Error build(bool EnsureSymtab)
Expected< std::unique_ptr< Object > > create(bool EnsureSymtab) const override
Error visit(Section &Sec) override
Error visit(const SymbolTableSection &Sec) override
Error finalize() override
ELFWriter(Object &Obj, raw_ostream &Out, bool WSH, bool OnlyKeepDebug)
Error accept(SectionVisitor &Visitor) const override
GnuDebugLinkSection(StringRef File, uint32_t PrecomputedCRC)
void setSymTab(const SymbolTableSection *SymTabSec)
void setSymbol(Symbol *S)
void replaceSectionReferences(const DenseMap< SectionBase *, SectionBase * > &FromTo) override
Error accept(SectionVisitor &) const override
void markSymbols() override
ArrayRef< uint8_t > Contents
void addMember(SectionBase *Sec)
Error removeSectionReferences(bool AllowBrokenLinks, function_ref< bool(const SectionBase *)> ToRemove) override
void setFlagWord(ELF::Elf32_Word W)
Error removeSymbols(function_ref< bool(const Symbol &)> ToRemove) override
Expected< std::unique_ptr< Object > > build()
Expected< std::unique_ptr< Object > > create(bool EnsureSymtab) const override
void writeSection(const SectionBase *Sec, ArrayRef< uint8_t > Data)
Error visit(const Section &Sec) final
virtual void writeData(uint8_t Type, uint16_t Addr, ArrayRef< uint8_t > Data)
void writeData(uint8_t Type, uint16_t Addr, ArrayRef< uint8_t > Data) override
Error visit(const StringTableSection &Sec) override
virtual Error visit(Section &Sec)=0
SectionTableRef sections() const
StringTableSection * SectionNames
bool isRelocatable() const
iterator_range< filter_iterator< pointee_iterator< std::vector< SecPtr >::const_iterator >, decltype(§ionIsAlloc)> > allocSections() const
Error updateSection(StringRef Name, ArrayRef< uint8_t > Data)
SectionIndexSection * SectionIndexTable
Error removeSymbols(function_ref< bool(const Symbol &)> ToRemove)
Error removeSections(bool AllowBrokenLinks, std::function< bool(const SectionBase &)> ToRemove)
SymbolTableSection * SymbolTable
Error addNewSymbolTable()
Error replaceSections(const DenseMap< SectionBase *, SectionBase * > &FromTo)
void appendHexData(StringRef HexData)
Error accept(SectionVisitor &Sec) const override
Error initialize(SectionTableRef SecTable) override
SymbolTableSection * Symbols
SectionBase * SecToApplyRel
StringRef getNamePrefix() const
void markSymbols() override
const Object & getObject() const
void addRelocation(const Relocation &Rel)
Error accept(SectionVisitor &Visitor) const override
Error removeSymbols(function_ref< bool(const Symbol &)> ToRemove) override
void replaceSectionReferences(const DenseMap< SectionBase *, SectionBase * > &FromTo) override
Error removeSectionReferences(bool AllowBrokenLinks, function_ref< bool(const SectionBase *)> ToRemove) override
std::vector< SRecord > Records
virtual void writeRecord(SRecord &Record, uint64_t Off)=0
void writeSection(const SectionBase &S, ArrayRef< uint8_t > Data)
Error visit(const Section &S) override
void writeRecords(uint32_t Entry)
Error visit(const StringTableSection &Sec) override
void writeRecord(SRecord &Record, uint64_t Off) override
virtual void markSymbols()
ArrayRef< uint8_t > OriginalData
virtual Error initialize(SectionTableRef SecTable)
virtual Error removeSectionReferences(bool AllowBrokenLinks, function_ref< bool(const SectionBase *)> ToRemove)
virtual void replaceSectionReferences(const DenseMap< SectionBase *, SectionBase * > &)
virtual Error removeSymbols(function_ref< bool(const Symbol &)> ToRemove)
virtual Error accept(SectionVisitor &Visitor) const =0
void addIndex(uint32_t Index)
void setSymTab(SymbolTableSection *SymTab)
Error accept(SectionVisitor &Visitor) const override
void reserve(size_t NumSymbols)
Error initialize(SectionTableRef SecTable) override
Expected< T * > getSectionOfType(uint32_t Index, Twine IndexErrMsg, Twine TypeErrMsg)
Expected< SectionBase * > getSection(uint32_t Index, Twine ErrMsg)
virtual Error visit(const Section &Sec)=0
Error visit(const Section &Sec) override
WritableMemoryBuffer & Out
Error removeSectionReferences(bool AllowBrokenLinks, function_ref< bool(const SectionBase *)> ToRemove) override
Error initialize(SectionTableRef SecTable) override
void restoreSymTabLink(SymbolTableSection &SymTab) override
Error accept(SectionVisitor &Visitor) const override
void addSection(const SectionBase *Sec)
void removeSection(const SectionBase *Sec)
const SectionBase * firstSection() const
ArrayRef< uint8_t > getContents() const
std::set< const SectionBase *, SectionCompare > Sections
void addString(StringRef Name)
uint32_t findIndex(StringRef Name) const
Error accept(SectionVisitor &Visitor) const override
const SectionBase * getStrTab() const
Error removeSectionReferences(bool AllowBrokenLinks, function_ref< bool(const SectionBase *)> ToRemove) override
const SectionIndexSection * getShndxTable() const
std::vector< std::unique_ptr< Symbol > > Symbols
SectionIndexSection * SectionIndexTable
Error accept(SectionVisitor &Visitor) const override
void addSymbol(Twine Name, uint8_t Bind, uint8_t Type, SectionBase *DefinedIn, uint64_t Value, uint8_t Visibility, uint16_t Shndx, uint64_t SymbolSize)
void updateSymbols(function_ref< void(Symbol &)> Callable)
Expected< const Symbol * > getSymbolByIndex(uint32_t Index) const
Error removeSymbols(function_ref< bool(const Symbol &)> ToRemove) override
Error initialize(SectionTableRef SecTable) override
void replaceSectionReferences(const DenseMap< SectionBase *, SectionBase * > &FromTo) override
std::unique_ptr< Symbol > SymPtr
void setShndxTable(SectionIndexSection *ShndxTable)
StringTableSection * SymbolNames
std::unique_ptr< WritableMemoryBuffer > Buf
const Elf_Ehdr & getHeader() const
static Expected< ELFFile > create(StringRef Object)
Expected< Elf_Phdr_Range > program_headers() const
Iterate over program header table.
size_t getBufSize() const
const uint8_t * base() const
Represents a GOFF physical record.
This class implements an extremely fast bulk output stream that can only output to a stream.
raw_ostream & write(unsigned char C)
A raw_ostream that writes to an SmallVector or SmallString.
This provides a very simple, boring adaptor for a begin and end iterator into a range type.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ C
The default llvm calling convention, compatible with C.
void encodeCrel(raw_ostream &OS, RelocsTy Relocs, F ToCrel)
const char * getReasonIfUnsupported(Format F)
Error decompress(DebugCompressionType T, ArrayRef< uint8_t > Input, uint8_t *Output, size_t UncompressedSize)
Format formatFor(DebugCompressionType Type)
void compress(Params P, ArrayRef< uint8_t > Input, SmallVectorImpl< uint8_t > &Output)
std::optional< const char * > toString(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract a string value from it.
StringRef toStringRef(const std::optional< DWARFFormValue > &V, StringRef Default={})
Take an optional DWARFFormValue and try to extract a string value from it.
support::ulittle32_t Word
void write(void *memory, value_type value, endianness endian)
Write a value to memory with a particular endianness.
StringRef filename(StringRef path, Style style=Style::native)
Get filename.
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
void stable_sort(R &&Range)
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
@ operation_not_permitted
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
void sort(IteratorTy Start, IteratorTy End)
bool is_sorted(R &&Range, Compare C)
Wrapper function around std::is_sorted to check if elements in a range R are sorted with respect to a...
@ Mod
The access may modify the value stored in memory.
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
OutputIt copy(R &&Range, OutputIt Out)
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
This struct is a compact representation of a valid (non-zero power of two) alignment.
static IHexLineData getLine(uint8_t Type, uint16_t Addr, ArrayRef< uint8_t > Data)
static uint8_t getChecksum(StringRef S)
static Expected< IHexRecord > parse(StringRef Line)
static size_t getLength(size_t DataSize)
static size_t getLineLength(size_t DataSize)
uint8_t getAddressSize() const
static SRecord getHeader(StringRef FileName)
uint8_t getChecksum() const
SRecLineData toString() const
static uint8_t getType(uint32_t Address)
uint16_t getShndx() const
SymbolShndxType ShndxType