30
30
#include " swift/Reflection/TypeRef.h"
31
31
#include " swift/Reflection/TypeRefBuilder.h"
32
32
#include " swift/Runtime/Unreachable.h"
33
- #include " ../../../stdlib/public/runtime/ImageInspectionELF.h"
34
33
35
34
#include < iostream>
36
35
#include < set>
@@ -60,15 +59,15 @@ template <unsigned char ELFClass> struct ELFTraits;
60
59
61
60
template <> struct ELFTraits <llvm::ELF::ELFCLASS32> {
62
61
using Header = const struct llvm ::ELF::Elf32_Ehdr;
63
- using ProgramHeader = const struct llvm ::ELF::Elf32_Phdr ;
62
+ using Section = const struct llvm ::ELF::Elf32_Shdr ;
64
63
using Offset = llvm::ELF::Elf32_Off;
65
64
using Size = llvm::ELF::Elf32_Word;
66
65
static constexpr unsigned char ELFClass = llvm::ELF::ELFCLASS32;
67
66
};
68
67
69
68
template <> struct ELFTraits <llvm::ELF::ELFCLASS64> {
70
69
using Header = const struct llvm ::ELF::Elf64_Ehdr;
71
- using ProgramHeader = const struct llvm ::ELF::Elf64_Phdr ;
70
+ using Section = const struct llvm ::ELF::Elf64_Shdr ;
72
71
using Offset = llvm::ELF::Elf64_Off;
73
72
using Size = llvm::ELF::Elf64_Xword;
74
73
static constexpr unsigned char ELFClass = llvm::ELF::ELFCLASS64;
@@ -113,7 +112,7 @@ class ReflectionContext
113
112
114
113
ReflectionContext (const ReflectionContext &other) = delete ;
115
114
ReflectionContext &operator =(const ReflectionContext &other) = delete ;
116
-
115
+
117
116
MemoryReader &getReader () {
118
117
return *this ->Reader ;
119
118
}
@@ -196,9 +195,9 @@ class ReflectionContext
196
195
// introduce misaligned pointers mapping between local and remote
197
196
// address space.
198
197
RangeStart = RangeStart & ~7 ;
199
- RangeEnd = RangeEnd + 7 & ~7 ;
198
+ RangeEnd = RangeEnd + 7 & ~7 ;
200
199
}
201
-
200
+
202
201
if (RangeStart == UINT64_MAX && RangeEnd == UINT64_MAX)
203
202
return false ;
204
203
@@ -387,105 +386,116 @@ class ReflectionContext
387
386
}
388
387
389
388
template <typename T> bool readELFSections (RemoteAddress ImageStart) {
390
- auto HeaderBuf =
389
+ auto Buf =
391
390
this ->getReader ().readBytes (ImageStart, sizeof (typename T::Header));
392
391
393
- auto Hdr = reinterpret_cast <const typename T::Header *>(HeaderBuf .get ());
392
+ auto Hdr = reinterpret_cast <const typename T::Header *>(Buf .get ());
394
393
assert (Hdr->getFileClass () == T::ELFClass && " invalid ELF file class" );
395
394
396
- const auto ProgramHdrAddress = ImageStart.getAddressData () + Hdr->e_phoff ;
397
- const auto NumEntries = Hdr->e_phnum ;
398
- const auto EntrySize = Hdr->e_phentsize ;
399
-
400
- uintptr_t MetadataSectionsPtrValue = 0 ;
401
- for (unsigned I = 0 ; I < NumEntries; ++I) {
402
- const StringRef MagicString =
403
- SWIFT_REFLECTION_METADATA_ELF_NOTE_MAGIC_STRING;
404
- auto ProgramHdrBuf = this ->getReader ().readBytes (
405
- RemoteAddress (ProgramHdrAddress + (I * EntrySize)), EntrySize);
406
- auto ProgramHdr = reinterpret_cast <const typename T::ProgramHeader *>(
407
- ProgramHdrBuf.get ());
408
- if (ProgramHdr->p_type != llvm::ELF::PT_NOTE ||
409
- ProgramHdr->p_memsz <= MagicString.size ())
410
- continue ;
411
- const auto SegmentAddr =
412
- ImageStart.getAddressData () + ProgramHdr->p_vaddr ;
413
- const auto SegmentSize = ProgramHdr->p_memsz ;
414
- auto SegmentBuf =
415
- this ->getReader ().readBytes (RemoteAddress (SegmentAddr), SegmentSize);
416
- const char *SegmentData =
417
- reinterpret_cast <const char *>(SegmentBuf.get ());
418
- if (!StringRef (SegmentData, SegmentSize).startswith (MagicString))
419
- continue ;
420
- MetadataSectionsPtrValue = *reinterpret_cast <const uintptr_t *>(
421
- SegmentData + MagicString.size () + 1 );
422
- break ;
395
+ // From the header, grab informations about the section header table.
396
+ auto SectionHdrAddress = ImageStart.getAddressData () + Hdr->e_shoff ;
397
+ auto SectionHdrNumEntries = Hdr->e_shnum ;
398
+ auto SectionEntrySize = Hdr->e_shentsize ;
399
+
400
+ // Collect all the section headers, we need them to look up the
401
+ // reflection sections (by name) and the string table.
402
+ std::vector<const typename T::Section *> SecHdrVec;
403
+ for (unsigned I = 0 ; I < SectionHdrNumEntries; ++I) {
404
+ auto SecBuf = this ->getReader ().readBytes (
405
+ RemoteAddress (SectionHdrAddress + (I * SectionEntrySize)),
406
+ SectionEntrySize);
407
+ auto SecHdr =
408
+ reinterpret_cast <const typename T::Section *>(SecBuf.get ());
409
+ SecHdrVec.push_back (SecHdr);
423
410
}
424
- if (!MetadataSectionsPtrValue)
425
- return false ;
426
411
427
- auto MetadataSectionsStructBuf = this ->getReader ().readBytes (
428
- RemoteAddress (MetadataSectionsPtrValue), sizeof (MetadataSections));
429
- const auto *Sections = reinterpret_cast <const MetadataSections *>(
430
- MetadataSectionsStructBuf.get ());
431
-
432
- auto BeginAddr = std::min (
433
- {Sections->swift5_fieldmd .start , Sections->swift5_assocty .start ,
434
- Sections->swift5_builtin .start , Sections->swift5_capture .start ,
435
- Sections->swift5_typeref .start , Sections->swift5_reflstr .start });
436
- auto EndAddr = std::max ({
437
- Sections->swift5_fieldmd .start + Sections->swift5_fieldmd .length ,
438
- Sections->swift5_assocty .start + Sections->swift5_assocty .length ,
439
- Sections->swift5_builtin .start + Sections->swift5_builtin .length ,
440
- Sections->swift5_capture .start + Sections->swift5_capture .length ,
441
- Sections->swift5_typeref .start + Sections->swift5_typeref .length ,
442
- Sections->swift5_reflstr .start + Sections->swift5_reflstr .length ,
443
- });
444
-
445
- // Extend the range [BeginAddr, EndAddr) to include the data segments.
446
- for (unsigned I = 0 ; I < NumEntries; ++I) {
447
- auto ProgramHdrBuf = this ->getReader ().readBytes (
448
- RemoteAddress (ProgramHdrAddress + (I * EntrySize)), EntrySize);
449
- auto ProgramHdr = reinterpret_cast <const typename T::ProgramHeader *>(
450
- ProgramHdrBuf.get ());
451
- if (ProgramHdr->p_type == llvm::ELF::PT_LOAD &&
452
- ProgramHdr->p_flags & (llvm::ELF::PF_W & llvm::ELF::PF_R)) {
453
- const decltype (BeginAddr) SegmentBeginAddr =
454
- ImageStart.getAddressData () + ProgramHdr->p_vaddr ;
455
- const decltype (BeginAddr) SegmentEndAddr =
456
- SegmentBeginAddr + ProgramHdr->p_memsz ;
457
- BeginAddr = std::min (BeginAddr, SegmentBeginAddr);
458
- EndAddr = std::max (EndAddr, SegmentEndAddr);
459
- }
412
+ // This provides quick access to the section header string table index.
413
+ // We also here handle the unlikely even where the section index overflows
414
+ // and it's just a pointer to secondary storage (SHN_XINDEX).
415
+ uint32_t SecIdx = Hdr->e_shstrndx ;
416
+ if (SecIdx == llvm::ELF::SHN_XINDEX) {
417
+ assert (!SecHdrVec.empty () && " malformed ELF object" );
418
+ SecIdx = SecHdrVec[0 ]->sh_link ;
460
419
}
461
420
462
- auto Buf = this ->getReader ().readBytes (RemoteAddress (BeginAddr),
463
- EndAddr - BeginAddr);
464
- auto RemoteAddrToRemoteRef = [&](uintptr_t Addr) -> RemoteRef<void > {
465
- return RemoteRef<void >(
466
- Addr, reinterpret_cast <void *>(
467
- reinterpret_cast <uintptr_t >(Buf.get ()) + Addr - BeginAddr));
421
+ assert (SecIdx < SecHdrVec.size () && " malformed ELF object" );
422
+
423
+ const typename T::Section *SecHdrStrTab = SecHdrVec[SecIdx];
424
+ typename T::Offset StrTabOffset = SecHdrStrTab->sh_offset ;
425
+ typename T::Size StrTabSize = SecHdrStrTab->sh_size ;
426
+
427
+ auto StrTabStart =
428
+ RemoteAddress (ImageStart.getAddressData () + StrTabOffset);
429
+ auto StrTabBuf = this ->getReader ().readBytes (StrTabStart, StrTabSize);
430
+ auto StrTab = reinterpret_cast <const char *>(StrTabBuf.get ());
431
+
432
+ auto findELFSectionByName = [&](std::string Name)
433
+ -> std::pair<RemoteRef<void >, uint64_t > {
434
+ // Now for all the sections, find their name.
435
+ for (const typename T::Section *Hdr : SecHdrVec) {
436
+ uint32_t Offset = Hdr->sh_name ;
437
+ auto SecName = std::string (StrTab + Offset);
438
+ if (SecName != Name)
439
+ continue ;
440
+ auto SecStart =
441
+ RemoteAddress (ImageStart.getAddressData () + Hdr->sh_addr );
442
+ auto SecSize = Hdr->sh_size ;
443
+ auto SecBuf = this ->getReader ().readBytes (SecStart, SecSize);
444
+ auto SecContents = RemoteRef<void >(SecStart.getAddressData (),
445
+ SecBuf.get ());
446
+ savedBuffers.push_back (std::move (SecBuf));
447
+ return {SecContents, SecSize};
448
+ }
449
+ return {nullptr , 0 };
468
450
};
469
- #define SECTION_INFO (NAME ) \
470
- {RemoteAddrToRemoteRef (Sections->NAME .start ), Sections->NAME .length }
471
- ReflectionInfo Info = {
472
- SECTION_INFO (swift5_fieldmd), SECTION_INFO (swift5_assocty),
473
- SECTION_INFO (swift5_builtin), SECTION_INFO (swift5_capture),
474
- SECTION_INFO (swift5_typeref), SECTION_INFO (swift5_reflstr),
475
- reinterpret_cast <uint64_t >(Buf.get ()), BeginAddr};
476
- #undef SECTION_INFO
477
- this ->addReflectionInfo (Info);
451
+
452
+ auto FieldMdSec = findELFSectionByName (" swift5_fieldmd" );
453
+ auto AssocTySec = findELFSectionByName (" swift5_assocty" );
454
+ auto BuiltinTySec = findELFSectionByName (" swift5_builtin" );
455
+ auto CaptureSec = findELFSectionByName (" swift5_capture" );
456
+ auto TypeRefMdSec = findELFSectionByName (" swift5_typeref" );
457
+ auto ReflStrMdSec = findELFSectionByName (" swift5_reflstr" );
458
+
459
+ // We succeed if at least one of the sections is present in the
460
+ // ELF executable.
461
+ if (FieldMdSec.first == nullptr &&
462
+ AssocTySec.first == nullptr &&
463
+ BuiltinTySec.first == nullptr &&
464
+ CaptureSec.first == nullptr &&
465
+ TypeRefMdSec.first == nullptr &&
466
+ ReflStrMdSec.first == nullptr )
467
+ return false ;
468
+
469
+ auto LocalStartAddress = reinterpret_cast <uint64_t >(Buf.get ());
470
+ auto RemoteStartAddress =
471
+ static_cast <uint64_t >(ImageStart.getAddressData ());
472
+
473
+ ReflectionInfo info = {
474
+ {FieldMdSec.first , FieldMdSec.second },
475
+ {AssocTySec.first , AssocTySec.second },
476
+ {BuiltinTySec.first , BuiltinTySec.second },
477
+ {CaptureSec.first , CaptureSec.second },
478
+ {TypeRefMdSec.first , TypeRefMdSec.second },
479
+ {ReflStrMdSec.first , ReflStrMdSec.second },
480
+ LocalStartAddress,
481
+ RemoteStartAddress};
482
+
483
+ this ->addReflectionInfo (info);
484
+
478
485
savedBuffers.push_back (std::move (Buf));
479
486
return true ;
480
487
}
481
-
488
+
482
489
bool readELF (RemoteAddress ImageStart) {
483
490
auto Buf =
484
491
this ->getReader ().readBytes (ImageStart, sizeof (llvm::ELF::Elf64_Ehdr));
492
+
485
493
// Read the header.
486
494
auto Hdr = reinterpret_cast <const llvm::ELF::Elf64_Ehdr *>(Buf.get ());
495
+
487
496
if (!Hdr->checkMagic ())
488
497
return false ;
498
+
489
499
// Check if we have a ELFCLASS32 or ELFCLASS64
490
500
unsigned char FileClass = Hdr->getFileClass ();
491
501
if (FileClass == llvm::ELF::ELFCLASS64) {
@@ -502,34 +512,34 @@ class ReflectionContext
502
512
auto Magic = this ->getReader ().readBytes (ImageStart, sizeof (uint32_t ));
503
513
if (!Magic)
504
514
return false ;
505
-
515
+
506
516
uint32_t MagicWord;
507
517
memcpy (&MagicWord, Magic.get (), sizeof (MagicWord));
508
-
518
+
509
519
// 32- and 64-bit Mach-O.
510
520
if (MagicWord == llvm::MachO::MH_MAGIC) {
511
521
return readMachOSections<MachOTraits<4 >>(ImageStart);
512
522
}
513
-
523
+
514
524
if (MagicWord == llvm::MachO::MH_MAGIC_64) {
515
525
return readMachOSections<MachOTraits<8 >>(ImageStart);
516
526
}
517
-
527
+
518
528
// PE. (This just checks for the DOS header; `readPECOFF` will further
519
529
// validate the existence of the PE header.)
520
530
auto MagicBytes = (const char *)Magic.get ();
521
531
if (MagicBytes[0 ] == ' M' && MagicBytes[1 ] == ' Z' ) {
522
532
return readPECOFF (ImageStart);
523
533
}
524
-
534
+
525
535
// ELF.
526
536
if (MagicBytes[0 ] == llvm::ELF::ElfMagic[0 ]
527
537
&& MagicBytes[1 ] == llvm::ELF::ElfMagic[1 ]
528
538
&& MagicBytes[2 ] == llvm::ELF::ElfMagic[2 ]
529
539
&& MagicBytes[3 ] == llvm::ELF::ElfMagic[3 ]) {
530
540
return readELF (ImageStart);
531
541
}
532
-
542
+
533
543
// We don't recognize the format.
534
544
return false ;
535
545
}
@@ -544,7 +554,7 @@ class ReflectionContext
544
554
return true ;
545
555
return ownsAddress (RemoteAddress (*MetadataAddress));
546
556
}
547
-
557
+
548
558
// / Returns true if the address falls within a registered image.
549
559
bool ownsAddress (RemoteAddress Address) {
550
560
for (auto Range : imageRanges) {
@@ -554,10 +564,10 @@ class ReflectionContext
554
564
&& Address.getAddressData () < End.getAddressData ())
555
565
return true ;
556
566
}
557
-
567
+
558
568
return false ;
559
569
}
560
-
570
+
561
571
// / Return a description of the layout of a class instance with the given
562
572
// / metadata as its isa pointer.
563
573
const TypeInfo *getMetadataTypeInfo (StoredPointer MetadataAddress) {
0 commit comments