@@ -335,6 +335,89 @@ template <class ELFT> class ELFStubBuilder {
335
335
write (Data + shdrOffset (Sec), Sec.Shdr );
336
336
}
337
337
};
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
+ };
338
421
} // end anonymous namespace
339
422
340
423
// / This function behaves similarly to StringRef::substr(), but attempts to
@@ -354,22 +437,6 @@ static Expected<StringRef> terminatedSubstr(StringRef Str, size_t Offset) {
354
437
return Str.substr (Offset, StrLen);
355
438
}
356
439
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
-
373
440
// / This function populates a DynamicEntries struct using an ELFT::DynRange.
374
441
// / After populating the struct, the members are validated with
375
442
// / some basic correctness checks.
@@ -508,7 +575,6 @@ template <class ELFT>
508
575
static Expected<std::unique_ptr<IFSStub>>
509
576
buildStub (const ELFObjectFile<ELFT> &ElfObj) {
510
577
using Elf_Dyn_Range = typename ELFT::DynRange;
511
- using Elf_Phdr_Range = typename ELFT::PhdrRange;
512
578
using Elf_Sym_Range = typename ELFT::SymRange;
513
579
using Elf_Sym = typename ELFT::Sym;
514
580
std::unique_ptr<IFSStub> DestStub = std::make_unique<IFSStub>();
@@ -519,25 +585,19 @@ buildStub(const ELFObjectFile<ELFT> &ElfObj) {
519
585
return DynTable.takeError ();
520
586
}
521
587
522
- // Fetch program headers.
523
- Expected<Elf_Phdr_Range> PHdrs = ElfFile.program_headers ();
524
- if (!PHdrs) {
525
- return PHdrs.takeError ();
526
- }
527
-
528
588
// Collect relevant .dynamic entries.
529
589
DynamicEntries DynEnt;
530
590
if (Error Err = populateDynamic<ELFT>(DynEnt, *DynTable))
531
591
return std::move (Err);
592
+ Expected<DynSym<ELFT>> EDynSym = DynSym<ELFT>::create (ElfFile, DynEnt);
593
+ if (!EDynSym)
594
+ return EDynSym.takeError ();
532
595
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 ();
538
599
539
- StringRef DynStr (reinterpret_cast <const char *>(DynStrPtr.get ()),
540
- DynEnt.StrSize );
600
+ StringRef DynStr = *EDynStr;
541
601
542
602
// Populate Arch from ELF header.
543
603
DestStub->Target .Arch = static_cast <IFSArch>(ElfFile.getHeader ().e_machine );
@@ -573,8 +633,7 @@ buildStub(const ELFObjectFile<ELFT> &ElfObj) {
573
633
return SymCount.takeError ();
574
634
if (*SymCount > 0 ) {
575
635
// 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 ();
578
637
if (!DynSymPtr)
579
638
return appendToError (DynSymPtr.takeError (),
580
639
" when locating .dynsym section contents" );
0 commit comments