28#include <unordered_set>
38 uint8_t *
B =
reinterpret_cast<uint8_t *
>(Buf->getBufferStart()) +
39 Obj.ProgramHdrSegment.Offset + Seg.
Index *
sizeof(Elf_Phdr);
40 Elf_Phdr &Phdr = *
reinterpret_cast<Elf_Phdr *
>(
B);
41 Phdr.p_type = Seg.
Type;
42 Phdr.p_flags = Seg.
Flags;
43 Phdr.p_offset = Seg.
Offset;
44 Phdr.p_vaddr = Seg.
VAddr;
45 Phdr.p_paddr = Seg.
PAddr;
48 Phdr.p_align = Seg.
Align;
69 reinterpret_cast<uint8_t *
>(Buf->getBufferStart()) + Sec.
HeaderOffset;
70 Elf_Shdr &
Shdr = *
reinterpret_cast<Elf_Shdr *
>(
B);
105 Sec.
Align = ELFT::Is64Bits ?
sizeof(Elf_Xword) :
sizeof(Elf_Word);
114 Sec.
Align = ELFT::Is64Bits ?
sizeof(Elf_Xword) :
sizeof(Elf_Word);
124 Sec.
Size =
sizeof(Elf_Word) + Sec.GroupMembers.size() *
sizeof(Elf_Word);
144 "cannot write symbol section index table '" +
150 "cannot write symbol table '" + Sec.
Name +
156 "cannot write relocation section '" + Sec.
Name +
162 "cannot write '" + Sec.
Name +
"' out to binary");
167 "cannot write '" + Sec.
Name +
"' out to binary");
179 return Addr > UINT32_MAX &&
Addr + 0x80000000 > UINT32_MAX;
192template <
class T,
class Iterator>
195 std::fill(It, It + Len,
'0');
197 for (
long I = Len - 1;
I >= 0; --
I) {
198 unsigned char Mod =
static_cast<unsigned char>(
X) & 15;
199 *(It +
I) = hexdigit(
Mod,
false);
208 uint8_t Checksum = 0;
210 Checksum += checkedGetHex<uint8_t>(S.
take_front(2));
220 auto Iter = Line.begin();
225 for (uint8_t
X :
Data)
227 StringRef S(Line.data() + 1, std::distance(Line.begin() + 1, Iter));
231 assert(Iter == Line.end());
238 if (R.HexData.size() == 0)
241 "zero data length is not allowed for data records");
248 if (R.HexData.size() != 4)
251 "segment address data should be 2 bytes in size");
255 if (R.HexData.size() != 8)
257 "start address data should be 4 bytes in size");
263 R.HexData.take_front(3) !=
"000")
265 "start address exceeds 20 bit for 80x86");
269 if (R.HexData.size() != 4)
272 "extended address data should be 2 bytes in size");
277 static_cast<unsigned>(R.Type));
289 "missing ':' in the beginning of line.");
291 for (
size_t Pos = 1; Pos < Line.size(); ++Pos)
292 if (hexDigitValue(Line[Pos]) == -1U)
294 "invalid character at position %zu.", Pos + 1);
302 if (Line.size() < 11)
304 "line is too short: %zu chars.", Line.size());
310 size_t DataLen = checkedGetHex<uint8_t>(Line.substr(1, 2));
313 "invalid line length %zu (should be %zu)",
316 Rec.
Addr = checkedGetHex<uint16_t>(Line.substr(3, 4));
317 Rec.
Type = checkedGetHex<uint8_t>(Line.substr(7, 2));
318 Rec.
HexData = Line.substr(9, DataLen * 2);
340 while (!
Data.empty()) {
341 uint64_t DataSize = std::min<uint64_t>(
Data.size(), ChunkSize);
342 if (
Addr > SegmentAddr + BaseAddr + 0xFFFFU) {
343 if (
Addr > 0xFFFFFU) {
346 if (SegmentAddr != 0)
347 SegmentAddr = writeSegmentAddr(0U);
348 BaseAddr = writeBaseAddr(
Addr);
351 SegmentAddr = writeSegmentAddr(
Addr);
355 assert(SegOffset <= 0xFFFFU);
356 DataSize = std::min(DataSize, 0x10000U - SegOffset);
365 uint8_t
Data[] = {
static_cast<uint8_t
>((
Addr & 0xF0000U) >> 12), 0};
367 return Addr & 0xF0000U;
373 uint8_t
Data[] = {
static_cast<uint8_t
>(
Base >> 24),
374 static_cast<uint8_t
>((
Base >> 16) & 0xFF)};
418 std::vector<uint8_t>
Data(Sec.
Size);
425 return Visitor.
visit(*
this);
429 return Visitor.
visit(*
this);
452 "--decompress-debug-sections: ch_type (" +
454 Sec.
Name +
"' is unsupported");
459 "failed to decompress section '" + Sec.
Name +
462 static_cast<size_t>(Sec.
Size)))
464 "failed to decompress section '" + Sec.
Name +
467 uint8_t *Buf =
reinterpret_cast<uint8_t *
>(Out.getBufferStart()) + Sec.
Offset;
468 std::copy(Decompressed.
begin(), Decompressed.
end(), Buf);
475 "cannot write compressed section '" + Sec.
Name +
480 return Visitor.
visit(*
this);
484 return Visitor.
visit(*
this);
488 return Visitor.
visit(*
this);
492 return Visitor.
visit(*
this);
497 while (!HexData.
empty()) {
506 "cannot write compressed section '" + Sec.
Name +
512 uint8_t *Buf =
reinterpret_cast<uint8_t *
>(Out.getBufferStart()) + Sec.
Offset;
514 switch (Sec.CompressionType) {
525 Chdr.ch_size = Sec.DecompressedSize;
526 Chdr.ch_addralign = Sec.DecompressedAlign;
527 memcpy(Buf, &Chdr,
sizeof(Chdr));
530 std::copy(Sec.CompressedData.begin(), Sec.CompressedData.end(), Buf);
537 :
SectionBase(Sec), CompressionType(CompressionType),
538 DecompressedSize(Sec.OriginalData.
size()), DecompressedAlign(Sec.
Align) {
545 Size = ChdrSize + CompressedData.
size();
553 DecompressedSize(DecompressedSize), DecompressedAlign(DecompressedAlign) {
558 return Visitor.
visit(*
this);
562 return Visitor.
visit(*
this);
583 return Visitor.
visit(*
this);
587 return Visitor.
visit(*
this);
592 uint8_t *Buf =
reinterpret_cast<uint8_t *
>(Out.getBufferStart()) + Sec.
Offset;
593 llvm::copy(Sec.Indexes,
reinterpret_cast<Elf_Word *
>(Buf));
605 " is not a symbol table");
617 return Visitor.
visit(*
this);
621 return Visitor.
visit(*
this);
681void SymbolTableSection::assignIndices() {
684 Sym->Index =
Index++;
696 if (DefinedIn !=
nullptr)
698 if (DefinedIn ==
nullptr) {
706 Sym.
Size = SymbolSize;
708 Symbols.emplace_back(std::make_unique<Symbol>(Sym));
717 if (!AllowBrokenLinks)
720 "string table '%s' cannot be removed because it is "
721 "referenced by the symbol table '%s'",
732 std::stable_partition(
751 for (std::unique_ptr<Symbol> &Sym :
Symbols)
761 "Symbol table has link index of " +
Twine(
Link) +
762 " which is not a valid index",
763 "Symbol table has link index of " +
Twine(
Link) +
764 " which is not a string table");
774 for (std::unique_ptr<Symbol> &Sym :
Symbols) {
778 MaxLocalIndex = std::max(MaxLocalIndex, Sym->Index);
782 Info = MaxLocalIndex + 1;
797 for (std::unique_ptr<Symbol> &Sym :
Symbols)
806 for (
const std::unique_ptr<Symbol> &Sym :
Symbols) {
807 if (Sym->DefinedIn !=
nullptr && Sym->DefinedIn->Index >=
SHN_LORESERVE)
828 return const_cast<Symbol *
>(*Sym);
833 Elf_Sym *Sym =
reinterpret_cast<Elf_Sym *
>(Out.getBufferStart() + Sec.
Offset);
849 return Visitor.
visit(*
this);
853 return Visitor.
visit(*
this);
870 if (!AllowBrokenLinks)
873 "symbol table '%s' cannot be removed because it is "
874 "referenced by the relocation section '%s'",
880 if (!R.RelocSymbol || !R.RelocSymbol->DefinedIn ||
881 !
ToRemove(R.RelocSymbol->DefinedIn))
884 "section '%s' cannot be removed: (%s+0x%" PRIx64
885 ") has relocation against symbol '%s'",
886 R.RelocSymbol->DefinedIn->Name.data(),
888 R.RelocSymbol->Name.c_str());
894template <
class SymTabType>
900 "Link field value " +
Twine(Link) +
" in section " +
Name +
902 "Link field value " +
Twine(Link) +
" in section " +
Name +
903 " is not a symbol table");
913 " in section " +
Name +
" is invalid");
924template <
class SymTabType>
926 this->Link = Symbols ? Symbols->Index : 0;
928 if (SecToApplyRel !=
nullptr)
929 this->
Info = SecToApplyRel->Index;
937 Rela.r_addend = Addend;
940template <
class RelRange,
class T>
941static void writeRel(
const RelRange &Relocations,
T *Buf,
bool IsMips64EL) {
942 for (
const auto &Reloc : Relocations) {
943 Buf->r_offset = Reloc.Offset;
945 Buf->setSymbolAndType(Reloc.RelocSymbol ? Reloc.RelocSymbol->Index : 0,
946 Reloc.Type, IsMips64EL);
953 uint8_t *Buf =
reinterpret_cast<uint8_t *
>(Out.getBufferStart()) + Sec.
Offset;
955 writeRel(Sec.Relocations,
reinterpret_cast<Elf_Rel *
>(Buf),
958 writeRel(Sec.Relocations,
reinterpret_cast<Elf_Rela *
>(Buf),
964 return Visitor.
visit(*
this);
968 return Visitor.
visit(*
this);
974 if (Reloc.RelocSymbol &&
ToRemove(*Reloc.RelocSymbol))
977 "not stripping symbol '%s' because it is named in a relocation",
978 Reloc.RelocSymbol->Name.data());
984 if (Reloc.RelocSymbol)
985 Reloc.RelocSymbol->Referenced =
true;
1001 return Visitor.
visit(*
this);
1005 return Visitor.
visit(*
this);
1011 if (!AllowBrokenLinks)
1014 "symbol table '%s' cannot be removed because it is "
1015 "referenced by the relocation section '%s'",
1029 bool AllowBrokenDependency,
1032 if (!AllowBrokenDependency)
1034 "section '%s' cannot be removed because it is "
1035 "referenced by the section '%s'",
1036 LinkSection->
Name.data(), this->Name.data());
1037 LinkSection =
nullptr;
1044 this->
Link = SymTab ? SymTab->
Index : 0;
1050 this->FlagWord &= ~GRP_COMDAT;
1056 if (!AllowBrokenLinks)
1059 "section '.symtab' cannot be removed because it is "
1060 "referenced by the group section '%s'",
1072 "symbol '%s' cannot be removed because it is "
1073 "referenced by the section '%s[%d]'",
1074 Sym->
Name.data(), this->Name.data(), this->Index);
1094 Sec->
Flags &= ~SHF_GROUP;
1103 " in section " +
Name +
" is invalid");
1110 LinkSection =
nullptr;
1127 Name =
".gnu_debuglink";
1136 : FileName(
File), CRC32(PrecomputedCRC) {
1140template <
class ELFT>
1142 unsigned char *Buf =
1143 reinterpret_cast<uint8_t *
>(Out.getBufferStart()) + Sec.
Offset;
1145 reinterpret_cast<Elf_Word *
>(Buf + Sec.
Size -
sizeof(Elf_Word));
1152 return Visitor.
visit(*
this);
1156 return Visitor.
visit(*
this);
1159template <
class ELFT>
1163 support::endian::write32<ELFT::TargetEndianness>(Buf++, Sec.FlagWord);
1165 support::endian::write32<ELFT::TargetEndianness>(Buf++, S->
Index);
1170 return Visitor.
visit(*
this);
1174 return Visitor.
visit(*
this);
1195 if (SectionIsTLS != SegmentIsTLS)
1218 if (
A->OriginalOffset <
B->OriginalOffset)
1220 if (
A->OriginalOffset >
B->OriginalOffset)
1222 return A->Index <
B->Index;
1229 Obj->ABIVersion = 0;
1239 StrTab.
Name =
".strtab";
1241 Obj->SectionNames = &StrTab;
1248 SymTab.
Name =
".symtab";
1249 SymTab.Link = StrTab->
Index;
1252 SymTab.addSymbol(
"", 0, 0,
nullptr, 0, 0, 0, 0);
1254 Obj->SymbolTable = &SymTab;
1271 DataSection.
Name =
".data";
1273 DataSection.Size =
Data.size();
1278 std::begin(SanitizedFilename), std::end(SanitizedFilename),
1279 [](
char C) {
return !isAlnum(
C); },
'_');
1280 Twine Prefix =
Twine(
"_binary_") + SanitizedFilename;
1283 0, NewSymbolVisibility, 0, 0);
1285 DataSection.Size, NewSymbolVisibility, 0, 0);
1287 DataSection.Size, NewSymbolVisibility,
SHN_ABS,
1297 return std::move(Err);
1300 return std::move(
Obj);
1305void IHexELFBuilder::addDataSections() {
1307 uint64_t SegmentAddr = 0, BaseAddr = 0;
1315 if (R.HexData.empty())
1317 RecAddr = R.Addr + SegmentAddr + BaseAddr;
1324 ".sec" + std::to_string(SecNo), RecAddr,
1328 Section->appendHexData(R.HexData);
1334 SegmentAddr = checkedGetHex<uint16_t>(R.HexData) << 4;
1338 Obj->Entry = checkedGetHex<uint32_t>(R.HexData);
1343 BaseAddr = checkedGetHex<uint16_t>(R.HexData) << 16;
1357 return std::move(Err);
1360 return std::move(
Obj);
1363template <
class ELFT>
1365 std::optional<StringRef> ExtractPartition)
1366 : ElfFile(ElfObj.getELFFile()), Obj(Obj),
1367 ExtractPartition(ExtractPartition) {
1372 for (
Segment &Parent : Obj.segments()) {
1388 if (!ExtractPartition)
1398 "could not find partition named '" +
1399 *ExtractPartition +
"'");
1402template <
class ELFT>
1412 if (Phdr.p_offset + Phdr.p_filesz > HeadersFile.
getBufSize())
1417 " goes past the end of the file");
1420 (size_t)Phdr.p_filesz};
1422 Seg.
Type = Phdr.p_type;
1423 Seg.
Flags = Phdr.p_flags;
1425 Seg.
Offset = Phdr.p_offset + EhdrOffset;
1426 Seg.
VAddr = Phdr.p_vaddr;
1427 Seg.
PAddr = Phdr.p_paddr;
1430 Seg.
Align = Phdr.p_align;
1440 auto &ElfHdr = Obj.ElfHdrSegment;
1442 ElfHdr.OriginalOffset = ElfHdr.Offset = EhdrOffset;
1444 const typename ELFT::Ehdr &Ehdr = HeadersFile.
getHeader();
1445 auto &PrHdr = Obj.ProgramHdrSegment;
1452 PrHdr.OriginalOffset = PrHdr.Offset = PrHdr.VAddr = EhdrOffset + Ehdr.e_phoff;
1454 PrHdr.FileSize = PrHdr.MemSize = Ehdr.e_phentsize * Ehdr.e_phnum;
1456 PrHdr.Align =
sizeof(Elf_Addr);
1457 PrHdr.Index =
Index++;
1461 for (
Segment &Child : Obj.segments())
1462 setParentSegment(Child);
1463 setParentSegment(ElfHdr);
1464 setParentSegment(PrHdr);
1469template <
class ELFT>
1473 "invalid alignment " +
Twine(GroupSec->
Align) +
1474 " of group section '" + GroupSec->
Name +
"'");
1477 auto SymTab = SecTable.template getSectionOfType<SymbolTableSection>(
1479 "link field value '" +
Twine(GroupSec->
Link) +
"' in section '" +
1480 GroupSec->
Name +
"' is invalid",
1481 "link field value '" +
Twine(GroupSec->
Link) +
"' in section '" +
1482 GroupSec->
Name +
"' is not a symbol table");
1484 return SymTab.takeError();
1489 "info field value '" +
Twine(GroupSec->
Info) +
1490 "' in section '" + GroupSec->
Name +
1491 "' is not a valid symbol index");
1498 "the content of the section " + GroupSec->
Name +
1505 support::endian::read32<ELFT::TargetEndianness>(Word++));
1507 uint32_t Index = support::endian::read32<ELFT::TargetEndianness>(Word);
1510 GroupSec->
Name +
"' is invalid");
1520template <
class ELFT>
1524 return Shdr.takeError();
1533 ElfFile.symbols(*
Shdr);
1535 return Symbols.takeError();
1542 return Name.takeError();
1547 "symbol '" + *
Name +
1548 "' has index SHN_XINDEX but no "
1549 "SHT_SYMTAB_SHNDX section exists");
1550 if (ShndxData.
data() ==
nullptr) {
1557 ElfFile.template getSectionContentsAsArray<Elf_Word>(**ShndxSec);
1559 return Data.takeError();
1562 if (ShndxData.
size() != Symbols->size())
1565 "symbol section index table does not have the same number of "
1566 "entries as the symbol table");
1568 Elf_Word
Index = ShndxData[&Sym - Symbols->begin()];
1571 "symbol '" + *
Name +
"' has invalid section index " +
Twine(
Index));
1580 "symbol '" + *
Name +
1581 "' has unsupported value greater than or equal "
1582 "to SHN_LORESERVE: " +
1583 Twine(Sym.st_shndx));
1587 Sym.st_shndx,
"symbol '" + *
Name +
1588 "' is defined has invalid section index " +
1589 Twine(Sym.st_shndx));
1596 SymTab->
addSymbol(*
Name, Sym.getBinding(), Sym.getType(), DefSection,
1597 Sym.getValue(), Sym.st_other, Sym.st_shndx, Sym.st_size);
1603template <
class ELFT>
1606template <
class ELFT>
1608 ToSet = Rela.r_addend;
1613 for (
const auto &Rel : RelRange) {
1615 ToAdd.
Offset = Rel.r_offset;
1623 "'" + Relocs->
Name +
"': relocation references symbol with index " +
1624 Twine(Sym) +
", but there is no symbol table");
1643 return Sections[
Index - 1].get();
1654 if (
T *Sec = dyn_cast<T>(*BaseSec))
1660template <
class ELFT>
1662 switch (
Shdr.sh_type) {
1669 return Data.takeError();
1680 return Data.takeError();
1690 return Data.takeError();
1695 return Data.takeError();
1700 return Data.takeError();
1705 return Data.takeError();
1708 if (Obj.SymbolTable !=
nullptr)
1710 "found multiple SHT_SYMTAB sections");
1712 Obj.SymbolTable = &SymTab;
1717 Obj.SectionIndexTable = &ShndxSection;
1718 return ShndxSection;
1725 return Data.takeError();
1729 return Name.takeError();
1735 *
Data, Chdr->ch_type, Chdr->ch_size, Chdr->ch_addralign));
1759 Sec->Name = SecName->str();
1760 Sec->Type = Sec->OriginalType =
Shdr.sh_type;
1761 Sec->Flags = Sec->OriginalFlags =
Shdr.sh_flags;
1762 Sec->Addr =
Shdr.sh_addr;
1763 Sec->Offset =
Shdr.sh_offset;
1764 Sec->OriginalOffset =
Shdr.sh_offset;
1765 Sec->Size =
Shdr.sh_size;
1766 Sec->Link =
Shdr.sh_link;
1767 Sec->Info =
Shdr.sh_info;
1768 Sec->Align =
Shdr.sh_addralign;
1769 Sec->EntrySize =
Shdr.sh_entsize;
1770 Sec->Index =
Index++;
1771 Sec->OriginalIndex = Sec->Index;
1773 ElfFile.base() +
Shdr.sh_offset,
1781 uint32_t ShstrIndex = ElfFile.getHeader().e_shstrndx;
1787 ShstrIndex = (*Sec)->sh_link;
1791 Obj.HadShdrs =
false;
1794 Obj.sections().template getSectionOfType<StringTableSection>(
1796 "e_shstrndx field value " +
Twine(ShstrIndex) +
" in elf header " +
1798 "e_shstrndx field value " +
Twine(ShstrIndex) +
" in elf header " +
1799 " does not reference a string table");
1803 Obj.SectionNames = *Sec;
1809 if (Obj.SectionIndexTable)
1810 if (
Error Err = Obj.SectionIndexTable->initialize(Obj.sections()))
1816 if (Obj.SymbolTable) {
1817 if (
Error Err = Obj.SymbolTable->initialize(Obj.sections()))
1819 if (
Error Err = initSymbolTable(Obj.SymbolTable))
1821 }
else if (EnsureSymtab) {
1822 if (
Error Err = Obj.addNewSymbolTable())
1830 if (&Sec == Obj.SymbolTable)
1832 if (
Error Err = Sec.initialize(Obj.sections()))
1834 if (
auto RelSec = dyn_cast<RelocationSection>(&Sec)) {
1841 Sections->begin() + RelSec->Index;
1842 if (RelSec->Type ==
SHT_REL) {
1844 ElfFile.rels(*
Shdr);
1852 ElfFile.relas(*
Shdr);
1859 }
else if (
auto GroupSec = dyn_cast<GroupSection>(&Sec)) {
1860 if (
Error Err = initGroupSection(GroupSec))
1869 if (
Error E = readSectionHeaders())
1871 if (
Error E = findEhdrOffset())
1878 {ElfFile.base() + EhdrOffset, ElfFile.getBufSize() - EhdrOffset}));
1884 Obj.OSABI = Ehdr.e_ident[
EI_OSABI];
1886 Obj.Type = Ehdr.e_type;
1887 Obj.Machine = Ehdr.e_machine;
1888 Obj.Version = Ehdr.e_version;
1889 Obj.Entry = Ehdr.e_entry;
1890 Obj.Flags = Ehdr.e_flags;
1892 if (
Error E = readSections(EnsureSymtab))
1894 return readProgramHeaders(*HeadersFile);
1908 std::vector<IHexRecord> Records;
1909 bool HasSections =
false;
1912 Records.reserve(Lines.size());
1913 for (
size_t LineNo = 1; LineNo <= Lines.size(); ++LineNo) {
1914 StringRef Line = Lines[LineNo - 1].trim();
1920 return parseError(LineNo, R.takeError());
1924 Records.push_back(*R);
1927 return parseError(-1U,
"no sections");
1929 return std::move(Records);
1942 auto Obj = std::make_unique<Object>();
1946 return std::move(Err);
1947 return std::move(Obj);
1951 return std::move(Err);
1952 return std::move(Obj);
1956 return std::move(Err);
1957 return std::move(Obj);
1961 return std::move(Err);
1962 return std::move(Obj);
1968 Elf_Ehdr &Ehdr = *
reinterpret_cast<Elf_Ehdr *
>(Buf->getBufferStart());
1969 std::fill(Ehdr.e_ident, Ehdr.e_ident + 16, 0);
1978 Ehdr.e_ident[
EI_OSABI] = Obj.OSABI;
1981 Ehdr.e_type = Obj.Type;
1982 Ehdr.e_machine = Obj.Machine;
1983 Ehdr.e_version = Obj.Version;
1984 Ehdr.e_entry = Obj.Entry;
1988 Ehdr.e_phoff = (Ehdr.e_phnum != 0) ? Obj.ProgramHdrSegment.Offset : 0;
1989 Ehdr.e_phentsize = (Ehdr.e_phnum != 0) ?
sizeof(Elf_Phdr) : 0;
1990 Ehdr.e_flags = Obj.Flags;
1991 Ehdr.e_ehsize =
sizeof(Elf_Ehdr);
1992 if (WriteSectionHeaders && Obj.sections().size() != 0) {
1993 Ehdr.e_shentsize =
sizeof(Elf_Shdr);
1994 Ehdr.e_shoff = Obj.SHOff;
2001 auto Shnum = Obj.sections().size() + 1;
2005 Ehdr.e_shnum = Shnum;
2015 Ehdr.e_shstrndx = Obj.SectionNames->Index;
2017 Ehdr.e_shentsize = 0;
2020 Ehdr.e_shstrndx = 0;
2025 for (
auto &Seg : Obj.segments())
2033 *
reinterpret_cast<Elf_Shdr *
>(Buf->getBufferStart() + Obj.SHOff);
2040 uint64_t Shnum = Obj.sections().size() + 1;
2042 Shdr.sh_size = Shnum;
2046 if (Obj.SectionNames !=
nullptr && Obj.SectionNames->Index >=
SHN_LORESERVE)
2047 Shdr.sh_link = Obj.SectionNames->Index;
2051 Shdr.sh_addralign = 0;
2052 Shdr.sh_entsize = 0;
2063 if (Sec.ParentSegment ==
nullptr)
2064 if (
Error Err = Sec.accept(*SecWriter))
2071 for (
Segment &Seg : Obj.segments()) {
2077 for (
auto it : Obj.getUpdatedSections()) {
2082 assert(Parent &&
"This section should've been part of a segment.");
2089 for (
auto &Sec : Obj.removedSections()) {
2090 Segment *Parent = Sec.ParentSegment;
2091 if (Parent ==
nullptr || Sec.Type ==
SHT_NOBITS || Sec.Size == 0)
2095 std::memset(Buf->getBufferStart() +
Offset, 0, Sec.Size);
2099template <
class ELFT>
2102 :
Writer(Obj, Buf), WriteSectionHeaders(WSH && Obj.HadShdrs),
2103 OnlyKeepDebug(OnlyKeepDebug) {}
2107 [&](
const SecPtr &Sec) {
return Sec->Name ==
Name; });
2108 if (It == Sections.end())
2110 Name.str().c_str());
2112 auto *OldSec = It->get();
2113 if (!OldSec->hasContents())
2116 "section '%s' cannot be updated because it does not have contents",
2117 Name.str().c_str());
2119 if (
Data.size() > OldSec->Size && OldSec->ParentSegment)
2121 "cannot fit data of size %zu into section '%s' "
2122 "with size %" PRIu64
" that is part of a segment",
2123 Data.size(),
Name.str().c_str(), OldSec->Size);
2125 if (!OldSec->ParentSegment) {
2126 *It = std::make_unique<OwnedDataSection>(*OldSec,
Data);
2129 OldSec->Size =
Data.size();
2130 UpdatedSections[OldSec] =
Data;
2139 auto Iter = std::stable_partition(
2140 std::begin(Sections), std::end(Sections), [=](
const SecPtr &Sec) {
2143 if (
auto RelSec = dyn_cast<RelocationSectionBase>(Sec.get())) {
2144 if (auto ToRelSec = RelSec->getSection())
2145 return !ToRemove(*ToRelSec);
2158 std::unordered_set<const SectionBase *> RemoveSections;
2159 RemoveSections.
reserve(std::distance(Iter, std::end(Sections)));
2160 for (
auto &RemoveSec :
make_range(Iter, std::end(Sections))) {
2161 for (
auto &
Segment : Segments)
2163 RemoveSec->onRemove();
2164 RemoveSections.insert(RemoveSec.get());
2172 for (
auto &KeepSec :
make_range(std::begin(Sections), Iter)) {
2173 if (
Error E = KeepSec->removeSectionReferences(
2174 AllowBrokenLinks, [&RemoveSections](
const SectionBase *Sec) {
2175 return RemoveSections.find(Sec) != RemoveSections.end();
2182 std::move(Iter, Sections.end(), std::back_inserter(RemovedSections));
2184 Sections.erase(Iter, std::end(Sections));
2190 auto SectionIndexLess = [](
const SecPtr &Lhs,
const SecPtr &Rhs) {
2191 return Lhs->Index < Rhs->Index;
2194 "Sections are expected to be sorted by Index");
2197 for (
auto &
I : FromTo)
2198 I.second->Index =
I.first->Index;
2201 for (
auto &Sec : Sections)
2202 Sec->replaceSectionReferences(FromTo);
2214 for (
const SecPtr &Sec : Sections)
2236 StrTab = &addSection<StringTableSection>();
2239 SymTab.
Name =
".symtab";
2243 SymTab.
addSymbol(
"", 0, 0,
nullptr, 0, 0, 0, 0);
2266 for (
Segment *Seg : Segments) {
2290template <
class Range>
2300 std::vector<SectionBase *> OutOfSegmentSections;
2302 for (
auto &Sec : Sections) {
2303 Sec.Index =
Index++;
2304 if (Sec.ParentSegment !=
nullptr) {
2305 auto Segment = *Sec.ParentSegment;
2309 OutOfSegmentSections.push_back(&Sec);
2316 for (
auto *Sec : OutOfSegmentSections) {
2330 std::vector<SectionBase *> Sections;
2334 Sec.Index =
Index++;
2335 Sections.push_back(&Sec);
2342 for (
auto *Sec : Sections) {
2343 auto *FirstSec = Sec->ParentSegment && Sec->ParentSegment->Type ==
PT_LOAD
2344 ? Sec->ParentSegment->firstSection()
2349 if (FirstSec && FirstSec == Sec)
2350 Off =
alignTo(Off, Sec->ParentSegment->Align, Sec->Addr);
2363 Off = Sec->Align ?
alignTo(Off, Sec->Align) : Off;
2364 }
else if (FirstSec != Sec) {
2367 Off = Sec->OriginalOffset - FirstSec->OriginalOffset + FirstSec->Offset;
2380 for (
Segment *Seg : Segments) {
2392 FirstSec ? FirstSec->
Offset
2406 FileSize = std::max(FileSize, HdrEnd -
Offset);
2411 MaxOffset = std::max(MaxOffset,
Offset + FileSize);
2417 Segment &ElfHdr = Obj.ElfHdrSegment;
2430 std::vector<Segment *> OrderedSegments;
2432 OrderedSegments.push_back(&
Segment);
2433 OrderedSegments.push_back(&Obj.ElfHdrSegment);
2434 OrderedSegments.push_back(&Obj.ProgramHdrSegment);
2438 if (OnlyKeepDebug) {
2443 sizeof(Elf_Ehdr) +
llvm::size(Obj.segments()) *
sizeof(Elf_Phdr);
2456 if (WriteSectionHeaders)
2464 if (!WriteSectionHeaders)
2466 size_t ShdrCount = Obj.sections().size() + 1;
2467 return Obj.SHOff + ShdrCount *
sizeof(Elf_Shdr);
2476 if (
Error E = writeSectionData())
2478 if (WriteSectionHeaders)
2483 Out.write(Buf->getBufferStart(), Buf->getBufferSize());
2510 if (Obj.SectionNames ==
nullptr && WriteSectionHeaders)
2512 "cannot write section header table because "
2513 "section header string table was removed");
2521 bool NeedsLargeIndexes =
false;
2533 if (NeedsLargeIndexes) {
2536 if (Obj.SymbolTable !=
nullptr && Obj.SectionIndexTable ==
nullptr) {
2540 Obj.SymbolTable->setShndxTable(&Shndx);
2546 if (Obj.SectionIndexTable !=
nullptr) {
2548 if (
Error E = Obj.removeSections(
false ,
2550 return &Sec == Obj.SectionIndexTable;
2558 if (Obj.SectionNames !=
nullptr)
2560 Obj.SectionNames->addString(Sec.Name);
2568 auto SecSizer = std::make_unique<ELFSectionSizer<ELFT>>();
2570 Sec.Index =
Index++;
2571 if (
Error Err = Sec.accept(*SecSizer))
2578 if (Obj.SymbolTable !=
nullptr)
2579 Obj.SymbolTable->prepareForLayout();
2584 if (
auto StrTab = dyn_cast<StringTableSection>(&Sec))
2585 StrTab->prepareForLayout();
2591 if (Obj.SymbolTable !=
nullptr)
2592 Obj.SymbolTable->fillShndxTable();
2598 Sec.HeaderOffset =
Offset;
2599 Offset +=
sizeof(Elf_Shdr);
2600 if (WriteSectionHeaders)
2601 Sec.NameIndex = Obj.SectionNames->findIndex(Sec.Name);
2605 size_t TotalSize = totalSize();
2609 "failed to allocate memory buffer of " +
2612 SecWriter = std::make_unique<ELFSectionWriter<ELFT>>(*Buf);
2618 if (
Error Err = Sec.accept(*SecWriter))
2636 if (Sec.ParentSegment !=
nullptr)
2637 Sec.Addr =
alignTo(Sec.Offset - Sec.ParentSegment->Offset +
2638 Sec.ParentSegment->PAddr,
2641 MinAddr = std::min(MinAddr, Sec.Addr);
2650 if (Sec.Type !=
SHT_NOBITS && Sec.Size > 0) {
2651 Sec.Offset = Sec.Addr - MinAddr;
2652 TotalSize = std::max(TotalSize, Sec.Offset + Sec.Size);
2658 "failed to allocate memory buffer of " +
2660 SecWriter = std::make_unique<BinarySectionWriter>(*
Buf);
2664bool IHexWriter::SectionCompare::operator()(
const SectionBase *Lhs,
2670uint64_t IHexWriter::writeEntryPointRecord(uint8_t *Buf) {
2672 uint8_t
Data[4] = {};
2688 return HexData.
size();
2691uint64_t IHexWriter::writeEndOfFileRecord(uint8_t *Buf) {
2694 return HexData.
size();
2706 Offset += writeEntryPointRecord(
2707 reinterpret_cast<uint8_t *
>(
Buf->getBufferStart()) +
Offset);
2709 Offset += writeEndOfFileRecord(
2710 reinterpret_cast<uint8_t *
>(
Buf->getBufferStart()) +
Offset);
2724 "Section '%s' address range [0x%llx, 0x%llx] is not 32 bit",
2733 "Entry point address 0x%llx overflows 32 bits",
2739 if (
Error E = checkSection(Sec))
2741 Sections.insert(&Sec);
2744 std::unique_ptr<WritableMemoryBuffer> EmptyBuffer =
2748 "failed to allocate memory buffer of 0 bytes");
2764 "failed to allocate memory buffer of " +
ReachingDefAnalysis InstSet & ToRemove
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
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")
return ToRemove size() > 0
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
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.
constexpr size_t size() const
size - Get the string size.
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.
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.
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
uint64_t getBufferOffset() const
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
Error finalize() 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 addRelocation(Relocation Rel)
void markSymbols() override
const Object & getObject() const
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
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
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
This class implements an extremely fast bulk output stream that can only output to a stream.
raw_ostream & write(unsigned char C)
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.
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)
uint16_t getShndx() const
SymbolShndxType ShndxType