@@ -335,6 +335,89 @@ template <class ELFT> class ELFStubBuilder {
335335 write (Data + shdrOffset (Sec), Sec.Shdr );
336336 }
337337};
338+
339+ // / This function takes an error, and appends a string of text to the end of
340+ // / that error. Since "appending" to an Error isn't supported behavior of an
341+ // / Error, this function technically creates a new error with the combined
342+ // / message and consumes the old error.
343+ // /
344+ // / @param Err Source error.
345+ // / @param After Text to append at the end of Err's error message.
346+ Error appendToError (Error Err, StringRef After) {
347+ std::string Message;
348+ raw_string_ostream Stream (Message);
349+ Stream << Err;
350+ Stream << " " << After;
351+ consumeError (std::move (Err));
352+ return createError (Stream.str ());
353+ }
354+
355+ template <class ELFT > class DynSym {
356+ using Elf_Shdr_Range = typename ELFT::ShdrRange;
357+ using Elf_Shdr = typename ELFT::Shdr;
358+
359+ public:
360+ static Expected<DynSym> create (const ELFFile<ELFT> &ElfFile,
361+ const DynamicEntries &DynEnt) {
362+ Expected<Elf_Shdr_Range> Shdrs = ElfFile.sections ();
363+ if (!Shdrs)
364+ return Shdrs.takeError ();
365+ return DynSym (ElfFile, DynEnt, *Shdrs);
366+ }
367+
368+ Expected<const uint8_t *> getDynSym () {
369+ if (DynSymHdr)
370+ return ElfFile.base () + DynSymHdr->sh_offset ;
371+ return getDynamicData (DynEnt.DynSymAddr , " dynamic symbol table" );
372+ }
373+
374+ Expected<StringRef> getDynStr () {
375+ if (DynSymHdr)
376+ return ElfFile.getStringTableForSymtab (*DynSymHdr, Shdrs);
377+ Expected<const uint8_t *> DataOrErr = getDynamicData (
378+ DynEnt.StrTabAddr , " dynamic string table" , DynEnt.StrSize );
379+ if (!DataOrErr)
380+ return DataOrErr.takeError ();
381+ return StringRef (reinterpret_cast <const char *>(*DataOrErr),
382+ DynEnt.StrSize );
383+ }
384+
385+ private:
386+ DynSym (const ELFFile<ELFT> &ElfFile, const DynamicEntries &DynEnt,
387+ Elf_Shdr_Range Shdrs)
388+ : ElfFile(ElfFile), DynEnt(DynEnt), Shdrs(Shdrs),
389+ DynSymHdr (findDynSymHdr()) {}
390+
391+ const Elf_Shdr *findDynSymHdr () {
392+ for (const Elf_Shdr &Sec : Shdrs)
393+ if (Sec.sh_type == SHT_DYNSYM) {
394+ // If multiple .dynsym are present, use the first one.
395+ // This behavior aligns with llvm::object::ELFFile::getDynSymtabSize()
396+ return &Sec;
397+ }
398+ return nullptr ;
399+ }
400+
401+ Expected<const uint8_t *> getDynamicData (uint64_t EntAddr, StringRef Name,
402+ uint64_t Size = 0 ) {
403+ Expected<const uint8_t *> SecPtr = ElfFile.toMappedAddr (EntAddr);
404+ if (!SecPtr)
405+ return appendToError (
406+ SecPtr.takeError (),
407+ (" when locating " + Name + " section contents" ).str ());
408+ Expected<const uint8_t *> SecEndPtr = ElfFile.toMappedAddr (EntAddr + Size);
409+ if (!SecEndPtr)
410+ return appendToError (
411+ SecEndPtr.takeError (),
412+ (" when locating " + Name + " section contents" ).str ());
413+ return *SecPtr;
414+ }
415+
416+ const ELFFile<ELFT> &ElfFile;
417+ const DynamicEntries &DynEnt;
418+ Elf_Shdr_Range Shdrs;
419+ const Elf_Shdr *DynSymHdr;
420+ };
338421} // end anonymous namespace
339422
340423// / This function behaves similarly to StringRef::substr(), but attempts to
@@ -354,22 +437,6 @@ static Expected<StringRef> terminatedSubstr(StringRef Str, size_t Offset) {
354437 return Str.substr (Offset, StrLen);
355438}
356439
357- // / This function takes an error, and appends a string of text to the end of
358- // / that error. Since "appending" to an Error isn't supported behavior of an
359- // / Error, this function technically creates a new error with the combined
360- // / message and consumes the old error.
361- // /
362- // / @param Err Source error.
363- // / @param After Text to append at the end of Err's error message.
364- Error appendToError (Error Err, StringRef After) {
365- std::string Message;
366- raw_string_ostream Stream (Message);
367- Stream << Err;
368- Stream << " " << After;
369- consumeError (std::move (Err));
370- return createError (Stream.str ());
371- }
372-
373440// / This function populates a DynamicEntries struct using an ELFT::DynRange.
374441// / After populating the struct, the members are validated with
375442// / some basic correctness checks.
@@ -508,7 +575,6 @@ template <class ELFT>
508575static Expected<std::unique_ptr<IFSStub>>
509576buildStub (const ELFObjectFile<ELFT> &ElfObj) {
510577 using Elf_Dyn_Range = typename ELFT::DynRange;
511- using Elf_Phdr_Range = typename ELFT::PhdrRange;
512578 using Elf_Sym_Range = typename ELFT::SymRange;
513579 using Elf_Sym = typename ELFT::Sym;
514580 std::unique_ptr<IFSStub> DestStub = std::make_unique<IFSStub>();
@@ -519,25 +585,19 @@ buildStub(const ELFObjectFile<ELFT> &ElfObj) {
519585 return DynTable.takeError ();
520586 }
521587
522- // Fetch program headers.
523- Expected<Elf_Phdr_Range> PHdrs = ElfFile.program_headers ();
524- if (!PHdrs) {
525- return PHdrs.takeError ();
526- }
527-
528588 // Collect relevant .dynamic entries.
529589 DynamicEntries DynEnt;
530590 if (Error Err = populateDynamic<ELFT>(DynEnt, *DynTable))
531591 return std::move (Err);
592+ Expected<DynSym<ELFT>> EDynSym = DynSym<ELFT>::create (ElfFile, DynEnt);
593+ if (!EDynSym)
594+ return EDynSym.takeError ();
532595
533- // Get pointer to in-memory location of .dynstr section.
534- Expected<const uint8_t *> DynStrPtr = ElfFile.toMappedAddr (DynEnt.StrTabAddr );
535- if (!DynStrPtr)
536- return appendToError (DynStrPtr.takeError (),
537- " when locating .dynstr section contents" );
596+ Expected<StringRef> EDynStr = EDynSym->getDynStr ();
597+ if (!EDynStr)
598+ return EDynStr.takeError ();
538599
539- StringRef DynStr (reinterpret_cast <const char *>(DynStrPtr.get ()),
540- DynEnt.StrSize );
600+ StringRef DynStr = *EDynStr;
541601
542602 // Populate Arch from ELF header.
543603 DestStub->Target .Arch = static_cast <IFSArch>(ElfFile.getHeader ().e_machine );
@@ -573,8 +633,7 @@ buildStub(const ELFObjectFile<ELFT> &ElfObj) {
573633 return SymCount.takeError ();
574634 if (*SymCount > 0 ) {
575635 // Get pointer to in-memory location of .dynsym section.
576- Expected<const uint8_t *> DynSymPtr =
577- ElfFile.toMappedAddr (DynEnt.DynSymAddr );
636+ Expected<const uint8_t *> DynSymPtr = EDynSym->getDynSym ();
578637 if (!DynSymPtr)
579638 return appendToError (DynSymPtr.takeError (),
580639 " when locating .dynsym section contents" );
0 commit comments