52 memset(&ElfHeader, 0,
sizeof(ElfHeader));
68 ElfHeader.e_ehsize =
sizeof(
typename ELFT::Ehdr);
69 ElfHeader.e_phentsize =
sizeof(
typename ELFT::Phdr);
70 ElfHeader.e_shentsize =
sizeof(
typename ELFT::Shdr);
74 template <
class ELFT>
struct OutputSection {
86 template <
class T,
class ELFT>
87 struct ContentSection :
public OutputSection<ELFT> {
89 ContentSection() { this->
NoBits =
false; }
99 template <
class ELFT>
class ELFSymbolTableBuilder {
101 using Elf_Sym =
typename ELFT::Sym;
103 ELFSymbolTableBuilder() { Symbols.push_back({}); }
105 void add(
size_t StNameOffset,
uint64_t StSize, uint8_t StBind, uint8_t StType,
106 uint8_t StOther,
uint16_t StShndx) {
108 S.st_name = StNameOffset;
110 S.st_info = (StBind << 4) | (StType & 0xf);
111 S.st_other = StOther;
112 S.st_shndx = StShndx;
113 Symbols.push_back(
S);
116 size_t getSize()
const {
return Symbols.size() *
sizeof(Elf_Sym); }
118 void write(uint8_t *Buf)
const {
119 memcpy(Buf, Symbols.data(),
sizeof(Elf_Sym) * Symbols.size());
126 template <
class ELFT>
class ELFDynamicTableBuilder {
128 using Elf_Dyn =
typename ELFT::Dyn;
133 Entry.d_un.d_ptr =
Addr;
134 Entries.push_back(Entry);
135 return Entries.size() - 1;
145 Entry.d_un.d_val =
Value;
146 Entries.push_back(Entry);
147 return Entries.size() - 1;
154 size_t getSize()
const {
156 return (Entries.size() + 1) *
sizeof(Elf_Dyn);
159 void write(uint8_t *Buf)
const {
160 memcpy(Buf, Entries.data(),
sizeof(Elf_Dyn) * Entries.size());
162 memset(Buf +
sizeof(Elf_Dyn) * Entries.size(), 0,
sizeof(Elf_Dyn));
169 template <
class ELFT>
class ELFStubBuilder {
171 using Elf_Ehdr =
typename ELFT::Ehdr;
173 using Elf_Phdr =
typename ELFT::Phdr;
174 using Elf_Sym =
typename ELFT::Sym;
176 using Elf_Dyn =
typename ELFT::Dyn;
178 ELFStubBuilder(
const ELFStubBuilder &) =
delete;
179 ELFStubBuilder(ELFStubBuilder &&) =
default;
181 explicit ELFStubBuilder(
const IFSStub &Stub) {
182 DynSym.Name =
".dynsym";
183 DynSym.Align =
sizeof(Elf_Addr);
184 DynStr.Name =
".dynstr";
186 DynTab.Name =
".dynamic";
187 DynTab.Align =
sizeof(Elf_Addr);
188 ShStrTab.Name =
".shstrtab";
192 for (
const IFSSymbol &Sym : Stub.Symbols)
193 DynStr.Content.add(Sym.Name);
194 for (
const std::string &Lib : Stub.NeededLibs)
195 DynStr.Content.add(Lib);
197 DynStr.Content.add(Stub.SoName.getValue());
199 std::vector<OutputSection<ELFT> *> Sections = {&DynSym, &DynStr, &DynTab,
201 const OutputSection<ELFT> *LastSection = Sections.back();
204 for (OutputSection<ELFT> *Sec : Sections) {
205 Sec->Index =
Index++;
206 ShStrTab.Content.add(Sec->Name);
208 ShStrTab.Content.finalize();
209 ShStrTab.Size = ShStrTab.Content.getSize();
210 DynStr.Content.finalize();
211 DynStr.Size = DynStr.Content.getSize();
214 for (
const IFSSymbol &Sym : Stub.Symbols) {
221 DynSym.Content.add(DynStr.Content.getOffset(Sym.Name),
Size, Bind,
224 DynSym.Size = DynSym.Content.getSize();
227 size_t DynSymIndex = DynTab.Content.addAddr(DT_SYMTAB, 0);
228 size_t DynStrIndex = DynTab.Content.addAddr(DT_STRTAB, 0);
229 DynTab.Content.addValue(DT_STRSZ, DynSym.Size);
230 for (
const std::string &Lib : Stub.NeededLibs)
231 DynTab.Content.addValue(DT_NEEDED, DynStr.Content.getOffset(Lib));
233 DynTab.Content.addValue(DT_SONAME,
234 DynStr.Content.getOffset(Stub.SoName.getValue()));
235 DynTab.Size = DynTab.Content.getSize();
237 uint64_t CurrentOffset =
sizeof(Elf_Ehdr);
238 for (OutputSection<ELFT> *Sec : Sections) {
239 Sec->Offset =
alignTo(CurrentOffset, Sec->Align);
240 Sec->Addr = Sec->Offset;
241 CurrentOffset = Sec->Offset + Sec->Size;
244 DynTab.Content.modifyAddr(DynSymIndex, DynSym.Addr);
245 DynTab.Content.modifyAddr(DynStrIndex, DynStr.Addr);
249 fillDynTabShdr(DynTab);
250 fillStrTabShdr(ShStrTab);
253 initELFHeader<ELFT>(ElfHeader,
254 static_cast<uint16_t>(Stub.Target.Arch.getValue()));
255 ElfHeader.e_shstrndx = ShStrTab.Index;
256 ElfHeader.e_shnum = LastSection->Index + 1;
258 alignTo(LastSection->Offset + LastSection->Size,
sizeof(Elf_Addr));
261 size_t getSize()
const {
262 return ElfHeader.e_shoff + ElfHeader.e_shnum *
sizeof(Elf_Shdr);
265 void write(uint8_t *Data)
const {
266 write(Data, ElfHeader);
267 DynSym.Content.write(Data + DynSym.Shdr.sh_offset);
268 DynStr.Content.write(Data + DynStr.Shdr.sh_offset);
269 DynTab.Content.write(Data + DynTab.Shdr.sh_offset);
270 ShStrTab.Content.write(Data + ShStrTab.Shdr.sh_offset);
271 writeShdr(Data, DynSym);
272 writeShdr(Data, DynStr);
273 writeShdr(Data, DynTab);
274 writeShdr(Data, ShStrTab);
279 ContentSection<ELFStringTableBuilder, ELFT> DynStr;
280 ContentSection<ELFStringTableBuilder, ELFT> ShStrTab;
281 ContentSection<ELFSymbolTableBuilder<ELFT>, ELFT> DynSym;
282 ContentSection<ELFDynamicTableBuilder<ELFT>, ELFT> DynTab;
284 template <
class T>
static void write(uint8_t *Data,
const T &
Value) {
288 void fillStrTabShdr(ContentSection<ELFStringTableBuilder, ELFT> &StrTab,
291 StrTab.Shdr.sh_flags = ShFlags;
292 StrTab.Shdr.sh_addr = StrTab.Addr;
293 StrTab.Shdr.sh_offset = StrTab.Offset;
294 StrTab.Shdr.sh_info = 0;
295 StrTab.Shdr.sh_size = StrTab.Size;
296 StrTab.Shdr.sh_name = ShStrTab.Content.getOffset(StrTab.Name);
297 StrTab.Shdr.sh_addralign = StrTab.Align;
298 StrTab.Shdr.sh_entsize = 0;
299 StrTab.Shdr.sh_link = 0;
301 void fillSymTabShdr(ContentSection<ELFSymbolTableBuilder<ELFT>, ELFT> &SymTab,
303 SymTab.Shdr.sh_type = ShType;
305 SymTab.Shdr.sh_addr = SymTab.Addr;
306 SymTab.Shdr.sh_offset = SymTab.Offset;
310 SymTab.Shdr.sh_info = 1;
311 SymTab.Shdr.sh_size = SymTab.Size;
312 SymTab.Shdr.sh_name = this->ShStrTab.Content.getOffset(SymTab.Name);
313 SymTab.Shdr.sh_addralign = SymTab.Align;
314 SymTab.Shdr.sh_entsize =
sizeof(Elf_Sym);
315 SymTab.Shdr.sh_link = this->DynStr.Index;
318 ContentSection<ELFDynamicTableBuilder<ELFT>, ELFT> &DynTab)
const {
321 DynTab.Shdr.sh_addr = DynTab.Addr;
322 DynTab.Shdr.sh_offset = DynTab.Offset;
323 DynTab.Shdr.sh_info = 0;
324 DynTab.Shdr.sh_size = DynTab.Size;
325 DynTab.Shdr.sh_name = this->ShStrTab.Content.getOffset(DynTab.Name);
326 DynTab.Shdr.sh_addralign = DynTab.Align;
327 DynTab.Shdr.sh_entsize =
sizeof(Elf_Dyn);
328 DynTab.Shdr.sh_link = this->DynStr.Index;
330 uint64_t shdrOffset(
const OutputSection<ELFT> &Sec)
const {
331 return ElfHeader.e_shoff + Sec.Index *
sizeof(Elf_Shdr);
334 void writeShdr(uint8_t *Data,
const OutputSection<ELFT> &Sec)
const {
335 write(Data + shdrOffset(Sec), Sec.Shdr);
355 template <
class ELFT>
class DynSym {
356 using Elf_Shdr_Range =
typename ELFT::ShdrRange;
361 const DynamicEntries &DynEnt) {
364 return Shdrs.takeError();
365 return DynSym(ElfFile, DynEnt, *Shdrs);
370 return ElfFile.base() + DynSymHdr->sh_offset;
371 return getDynamicData(DynEnt.DynSymAddr,
"dynamic symbol table");
376 return ElfFile.getStringTableForSymtab(*DynSymHdr, Shdrs);
378 DynEnt.StrTabAddr,
"dynamic string table", DynEnt.StrSize);
381 return StringRef(
reinterpret_cast<const char *
>(*DataOrErr),
386 DynSym(
const ELFFile<ELFT> &ElfFile,
const DynamicEntries &DynEnt,
387 Elf_Shdr_Range Shdrs)
388 : ElfFile(ElfFile), DynEnt(DynEnt), Shdrs(Shdrs),
389 DynSymHdr(findDynSymHdr()) {}
391 const Elf_Shdr *findDynSymHdr() {
392 for (
const Elf_Shdr &Sec : Shdrs)
405 return appendToError(
407 (
"when locating " +
Name +
" section contents").str());
410 return appendToError(
412 (
"when locating " +
Name +
" section contents").str());
417 const DynamicEntries &DynEnt;
418 Elf_Shdr_Range Shdrs;
419 const Elf_Shdr *DynSymHdr;
430 size_t StrEnd = Str.find(
'\0', Offset);
433 "String overran bounds of string table (no null terminator)");
436 size_t StrLen = StrEnd - Offset;
437 return Str.substr(Offset, StrLen);
446 template <
class ELFT>
448 typename ELFT::DynRange DynTable) {
449 if (DynTable.empty())
453 bool FoundDynStr =
false;
454 bool FoundDynStrSz =
false;
455 bool FoundDynSym =
false;
456 for (
auto &Entry : DynTable) {
457 switch (Entry.d_tag) {
466 Dyn.
StrSize = Entry.d_un.d_val;
467 FoundDynStrSz =
true;
477 Dyn.
ElfHash = Entry.d_un.d_ptr;
480 Dyn.
GnuHash = Entry.d_un.d_ptr;
486 "Couldn't locate dynamic string table (no DT_STRTAB entry)");
488 if (!FoundDynStrSz) {
490 "Couldn't determine dynamic string table size (no DT_STRSZ entry)");
494 "Couldn't locate dynamic symbol table (no DT_SYMTAB entry)");
498 "DT_SONAME string offset (0x%016" PRIx64
499 ") outside of dynamic string table",
505 "DT_NEEDED string offset (0x%016" PRIx64
506 ") outside of dynamic string table",
519 template <
class ELFT>
521 const typename ELFT::Sym &RawSym) {
522 IFSSymbol TargetSym{std::string(SymName)};
523 uint8_t Binding = RawSym.getBinding();
525 TargetSym.Weak =
true;
527 TargetSym.Weak =
false;
529 TargetSym.Undefined = RawSym.isUndefined();
532 if (TargetSym.Type == IFSSymbolType::Func) {
535 TargetSym.Size = RawSym.st_size;
546 template <
class ELFT>
548 const typename ELFT::SymRange DynSym,
551 for (
auto RawSym : DynSym.drop_front(1)) {
553 uint8_t Binding = RawSym.getBinding();
557 uint8_t Visibility = RawSym.getVisibility();
565 IFSSymbol Sym = createELFSym<ELFT>(*SymName, RawSym);
574 template <
class ELFT>
577 using Elf_Dyn_Range =
typename ELFT::DynRange;
578 using Elf_Sym_Range =
typename ELFT::SymRange;
579 using Elf_Sym =
typename ELFT::Sym;
580 std::unique_ptr<IFSStub> DestStub = std::make_unique<IFSStub>();
590 if (
Error Err = populateDynamic<ELFT>(DynEnt, *DynTable))
603 DestStub->Target.Arch =
static_cast<IFSArch>(ElfFile.getHeader().e_machine);
604 DestStub->Target.BitWidth =
606 DestStub->Target.Endianness =
608 DestStub->Target.ObjectFormat =
"ELF";
611 if (DynEnt.SONameOffset.hasValue()) {
615 return appendToError(NameOrErr.
takeError(),
"when reading DT_SONAME");
617 DestStub->SoName = std::string(*NameOrErr);
621 for (
uint64_t NeededStrOffset : DynEnt.NeededLibNames) {
625 return appendToError(LibNameOrErr.
takeError(),
"when reading DT_NEEDED");
627 DestStub->NeededLibs.push_back(std::string(*LibNameOrErr));
638 return appendToError(DynSymPtr.
takeError(),
639 "when locating .dynsym section contents");
641 reinterpret_cast<const Elf_Sym *
>(*DynSymPtr), *SymCount);
642 Error SymReadError = populateSymbols<ELFT>(*DestStub, DynSyms, DynStr);
644 return appendToError(
std::move(SymReadError),
645 "when reading dynamic symbols");
656 template <
class ELFT>
659 ELFStubBuilder<ELFT>
Builder{Stub};
661 std::vector<uint8_t> Buf(
Builder.getSize());
665 if (
ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrError =
669 if ((*BufOrError)->getBufferSize() ==
Builder.getSize() &&
670 !
memcmp((*BufOrError)->getBufferStart(), Buf.data(),
681 " when trying to open `" + FilePath +
685 std::unique_ptr<FileOutputBuffer> FileBuf =
std::move(*BufOrError);
686 memcpy(FileBuf->getBufferStart(), Buf.data(), Buf.size());
688 return FileBuf->commit();
719 return writeELFBinaryToFile<ELF32LE>(FilePath, Stub,
WriteIfChanged);
721 return writeELFBinaryToFile<ELF32BE>(FilePath, Stub,
WriteIfChanged);
725 return writeELFBinaryToFile<ELF64LE>(FilePath, Stub,
WriteIfChanged);
727 return writeELFBinaryToFile<ELF64BE>(FilePath, Stub,
WriteIfChanged);