34 uint64_t StrTabAddr = 0;
39 uint64_t DynSymAddr = 0;
54 memset(&ElfHeader, 0,
sizeof(ElfHeader));
70 ElfHeader.e_ehsize =
sizeof(
typename ELFT::Ehdr);
71 ElfHeader.e_phentsize =
sizeof(
typename ELFT::Phdr);
72 ElfHeader.e_shentsize =
sizeof(
typename ELFT::Shdr);
76 template <
class ELFT>
struct OutputSection {
88 template <
class T,
class ELFT>
89 struct ContentSection :
public OutputSection<ELFT> {
91 ContentSection() { this->
NoBits =
false; }
101 template <
class ELFT>
class ELFSymbolTableBuilder {
103 using Elf_Sym =
typename ELFT::Sym;
105 ELFSymbolTableBuilder() { Symbols.push_back({}); }
107 void add(
size_t StNameOffset, uint64_t StSize, uint8_t StBind, uint8_t StType,
108 uint8_t StOther,
uint16_t StShndx) {
110 S.st_name = StNameOffset;
112 S.st_info = (StBind << 4) | (StType & 0xf);
113 S.st_other = StOther;
114 S.st_shndx = StShndx;
115 Symbols.push_back(
S);
118 size_t getSize()
const {
return Symbols.size() *
sizeof(Elf_Sym); }
120 void write(uint8_t *Buf)
const {
121 memcpy(Buf, Symbols.data(),
sizeof(Elf_Sym) * Symbols.size());
128 template <
class ELFT>
class ELFDynamicTableBuilder {
130 using Elf_Dyn =
typename ELFT::Dyn;
132 size_t addAddr(uint64_t Tag, uint64_t
Addr) {
135 Entry.d_un.d_ptr =
Addr;
136 Entries.push_back(Entry);
137 return Entries.size() - 1;
140 void modifyAddr(
size_t Index, uint64_t
Addr) {
144 size_t addValue(uint64_t Tag, uint64_t
Value) {
147 Entry.d_un.d_val =
Value;
148 Entries.push_back(Entry);
149 return Entries.size() - 1;
152 void modifyValue(
size_t Index, uint64_t
Value) {
156 size_t getSize()
const {
158 return (Entries.size() + 1) *
sizeof(Elf_Dyn);
161 void write(uint8_t *Buf)
const {
162 memcpy(Buf, Entries.data(),
sizeof(Elf_Dyn) * Entries.size());
164 memset(Buf +
sizeof(Elf_Dyn) * Entries.size(), 0,
sizeof(Elf_Dyn));
171 template <
class ELFT>
class ELFStubBuilder {
173 using Elf_Ehdr =
typename ELFT::Ehdr;
175 using Elf_Phdr =
typename ELFT::Phdr;
176 using Elf_Sym =
typename ELFT::Sym;
178 using Elf_Dyn =
typename ELFT::Dyn;
180 ELFStubBuilder(
const ELFStubBuilder &) =
delete;
181 ELFStubBuilder(ELFStubBuilder &&) =
default;
183 explicit ELFStubBuilder(
const ELFStub &Stub) {
184 DynSym.Name =
".dynsym";
185 DynSym.Align =
sizeof(Elf_Addr);
186 DynStr.Name =
".dynstr";
188 DynTab.Name =
".dynamic";
189 DynTab.Align =
sizeof(Elf_Addr);
190 ShStrTab.Name =
".shstrtab";
194 for (
const ELFSymbol &Sym : Stub.Symbols)
195 DynStr.Content.add(Sym.Name);
196 for (
const std::string &Lib : Stub.NeededLibs)
197 DynStr.Content.add(Lib);
199 DynStr.Content.add(Stub.SoName.getValue());
201 std::vector<OutputSection<ELFT> *> Sections = {&DynSym, &DynStr, &DynTab,
203 const OutputSection<ELFT> *LastSection = Sections.back();
206 for (OutputSection<ELFT> *Sec : Sections) {
207 Sec->Index =
Index++;
208 ShStrTab.Content.add(Sec->Name);
210 ShStrTab.Content.finalize();
211 ShStrTab.Size = ShStrTab.Content.getSize();
212 DynStr.Content.finalize();
213 DynStr.Size = DynStr.Content.getSize();
216 for (
const ELFSymbol &Sym : Stub.Symbols) {
222 DynSym.Content.add(DynStr.Content.getOffset(Sym.Name), Sym.Size, Bind,
223 (uint8_t)Sym.Type, 0, Shndx);
225 DynSym.Size = DynSym.Content.getSize();
228 size_t DynSymIndex = DynTab.Content.addAddr(DT_SYMTAB, 0);
229 size_t DynStrIndex = DynTab.Content.addAddr(DT_STRTAB, 0);
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, Stub.Arch);
254 ElfHeader.e_shstrndx = ShStrTab.Index;
255 ElfHeader.e_shnum = LastSection->Index + 1;
257 alignTo(LastSection->Offset + LastSection->Size,
sizeof(Elf_Addr));
260 size_t getSize()
const {
261 return ElfHeader.e_shoff + ElfHeader.e_shnum *
sizeof(Elf_Shdr);
264 void write(uint8_t *Data)
const {
265 write(Data, ElfHeader);
266 DynSym.Content.write(Data + DynSym.Shdr.sh_offset);
267 DynStr.Content.write(Data + DynStr.Shdr.sh_offset);
268 DynTab.Content.write(Data + DynTab.Shdr.sh_offset);
269 ShStrTab.Content.write(Data + ShStrTab.Shdr.sh_offset);
270 writeShdr(Data, DynSym);
271 writeShdr(Data, DynStr);
272 writeShdr(Data, DynTab);
273 writeShdr(Data, ShStrTab);
278 ContentSection<ELFStringTableBuilder, ELFT> DynStr;
279 ContentSection<ELFStringTableBuilder, ELFT> ShStrTab;
280 ContentSection<ELFSymbolTableBuilder<ELFT>, ELFT> DynSym;
281 ContentSection<ELFDynamicTableBuilder<ELFT>, ELFT> DynTab;
283 template <
class T>
static void write(uint8_t *Data,
const T &
Value) {
287 void fillStrTabShdr(ContentSection<ELFStringTableBuilder, ELFT> &StrTab,
290 StrTab.Shdr.sh_flags = ShFlags;
291 StrTab.Shdr.sh_addr = StrTab.Addr;
292 StrTab.Shdr.sh_offset = StrTab.Offset;
293 StrTab.Shdr.sh_info = 0;
294 StrTab.Shdr.sh_size = StrTab.Size;
295 StrTab.Shdr.sh_name = ShStrTab.Content.getOffset(StrTab.Name);
296 StrTab.Shdr.sh_addralign = StrTab.Align;
297 StrTab.Shdr.sh_entsize = 0;
298 StrTab.Shdr.sh_link = 0;
300 void fillSymTabShdr(ContentSection<ELFSymbolTableBuilder<ELFT>, ELFT> &SymTab,
302 SymTab.Shdr.sh_type = ShType;
304 SymTab.Shdr.sh_addr = SymTab.Addr;
305 SymTab.Shdr.sh_offset = SymTab.Offset;
309 SymTab.Shdr.sh_info = 1;
310 SymTab.Shdr.sh_size = SymTab.Size;
311 SymTab.Shdr.sh_name = this->ShStrTab.Content.getOffset(SymTab.Name);
312 SymTab.Shdr.sh_addralign = SymTab.Align;
313 SymTab.Shdr.sh_entsize =
sizeof(Elf_Sym);
314 SymTab.Shdr.sh_link = this->DynStr.Index;
317 ContentSection<ELFDynamicTableBuilder<ELFT>, ELFT> &DynTab)
const {
320 DynTab.Shdr.sh_addr = DynTab.Addr;
321 DynTab.Shdr.sh_offset = DynTab.Offset;
322 DynTab.Shdr.sh_info = 0;
323 DynTab.Shdr.sh_size = DynTab.Size;
324 DynTab.Shdr.sh_name = this->ShStrTab.Content.getOffset(DynTab.Name);
325 DynTab.Shdr.sh_addralign = DynTab.Align;
326 DynTab.Shdr.sh_entsize =
sizeof(Elf_Dyn);
327 DynTab.Shdr.sh_link = this->DynStr.Index;
329 uint64_t shdrOffset(
const OutputSection<ELFT> &Sec)
const {
330 return ElfHeader.e_shoff + Sec.Index *
sizeof(Elf_Shdr);
333 void writeShdr(uint8_t *Data,
const OutputSection<ELFT> &Sec)
const {
334 write(Data + shdrOffset(Sec), Sec.Shdr);
349 "String overran bounds of string table (no null terminator)");
352 size_t StrLen = StrEnd -
Offset;
367 Stream <<
" " << After;
378 template <
class ELFT>
380 typename ELFT::DynRange DynTable) {
381 if (DynTable.empty())
385 bool FoundDynStr =
false;
386 bool FoundDynStrSz =
false;
387 bool FoundDynSym =
false;
388 for (
auto &Entry : DynTable) {
389 switch (Entry.d_tag) {
398 Dyn.
StrSize = Entry.d_un.d_val;
399 FoundDynStrSz =
true;
409 Dyn.
ElfHash = Entry.d_un.d_ptr;
412 Dyn.
GnuHash = Entry.d_un.d_ptr;
418 "Couldn't locate dynamic string table (no DT_STRTAB entry)");
420 if (!FoundDynStrSz) {
422 "Couldn't determine dynamic string table size (no DT_STRSZ entry)");
426 "Couldn't locate dynamic symbol table (no DT_SYMTAB entry)");
430 "DT_SONAME string offset (0x%016" PRIx64
431 ") outside of dynamic string table",
437 "DT_NEEDED string offset (0x%016" PRIx64
438 ") outside of dynamic string table",
456 return ELFSymbolType::NoType;
458 return ELFSymbolType::Object;
460 return ELFSymbolType::Func;
462 return ELFSymbolType::TLS;
473 template <
class ELFT>
475 const typename ELFT::Sym &RawSym) {
476 ELFSymbol TargetSym{std::string(SymName)};
477 uint8_t Binding = RawSym.getBinding();
479 TargetSym.
Weak =
true;
481 TargetSym.Weak =
false;
483 TargetSym.Undefined = RawSym.isUndefined();
486 if (TargetSym.Type == ELFSymbolType::Func) {
489 TargetSym.Size = RawSym.st_size;
500 template <
class ELFT>
502 const typename ELFT::SymRange DynSym,
505 for (
auto RawSym : DynSym.drop_front(1)) {
507 uint8_t Binding = RawSym.getBinding();
511 uint8_t Visibility = RawSym.getVisibility();
519 ELFSymbol Sym = createELFSym<ELFT>(*SymName, RawSym);
528 template <
class ELFT>
531 using Elf_Dyn_Range =
typename ELFT::DynRange;
532 using Elf_Phdr_Range =
typename ELFT::PhdrRange;
533 using Elf_Sym_Range =
typename ELFT::SymRange;
534 using Elf_Sym =
typename ELFT::Sym;
535 std::unique_ptr<ELFStub> DestStub = std::make_unique<ELFStub>();
551 if (
Error Err = populateDynamic<ELFT>(DynEnt, *DynTable))
558 "when locating .dynstr section contents");
560 StringRef DynStr(
reinterpret_cast<const char *
>(DynStrPtr.
get()),
564 DestStub->Arch = ElfFile.
getHeader().e_machine;
573 DestStub->SoName = std::string(*NameOrErr);
583 DestStub->NeededLibs.push_back(std::string(*LibNameOrErr));
596 "when locating .dynsym section contents");
598 reinterpret_cast<const Elf_Sym *
>(*DynSymPtr), *SymCount);
599 Error SymReadError = populateSymbols<ELFT>(*DestStub, DynSyms, DynStr);
602 "when reading dynamic symbols");
613 template <
class ELFT>
616 ELFStubBuilder<ELFT>
Builder{Stub};
618 std::vector<uint8_t> Buf(
Builder.getSize());
622 if (
ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrError =
626 if ((*BufOrError)->getBufferSize() ==
Builder.getSize() &&
627 !
memcmp((*BufOrError)->getBufferStart(), Buf.data(),
638 " when trying to open `" + FilePath +
642 std::unique_ptr<FileOutputBuffer> FileBuf =
std::move(*BufOrError);
643 memcpy(FileBuf->getBufferStart(), Buf.data(), Buf.size());
645 return FileBuf->commit();
672 return writeELFBinaryToFile<ELF32LE>(FilePath, Stub,
WriteIfChanged);
674 return writeELFBinaryToFile<ELF32BE>(FilePath, Stub,
WriteIfChanged);
676 return writeELFBinaryToFile<ELF64LE>(FilePath, Stub,
WriteIfChanged);
678 return writeELFBinaryToFile<ELF64BE>(FilePath, Stub,
WriteIfChanged);