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"
33
34
34
35
#include < iostream>
35
36
#include < set>
@@ -59,15 +60,15 @@ template <unsigned char ELFClass> struct ELFTraits;
59
60
60
61
template <> struct ELFTraits <llvm::ELF::ELFCLASS32> {
61
62
using Header = const struct llvm ::ELF::Elf32_Ehdr;
62
- using Section = const struct llvm ::ELF::Elf32_Shdr ;
63
+ using ProgramHeader = const struct llvm ::ELF::Elf32_Phdr ;
63
64
using Offset = llvm::ELF::Elf32_Off;
64
65
using Size = llvm::ELF::Elf32_Word;
65
66
static constexpr unsigned char ELFClass = llvm::ELF::ELFCLASS32;
66
67
};
67
68
68
69
template <> struct ELFTraits <llvm::ELF::ELFCLASS64> {
69
70
using Header = const struct llvm ::ELF::Elf64_Ehdr;
70
- using Section = const struct llvm ::ELF::Elf64_Shdr ;
71
+ using ProgramHeader = const struct llvm ::ELF::Elf64_Phdr ;
71
72
using Offset = llvm::ELF::Elf64_Off;
72
73
using Size = llvm::ELF::Elf64_Xword;
73
74
static constexpr unsigned char ELFClass = llvm::ELF::ELFCLASS64;
@@ -112,7 +113,7 @@ class ReflectionContext
112
113
113
114
ReflectionContext (const ReflectionContext &other) = delete ;
114
115
ReflectionContext &operator =(const ReflectionContext &other) = delete ;
115
-
116
+
116
117
MemoryReader &getReader () {
117
118
return *this ->Reader ;
118
119
}
@@ -195,9 +196,9 @@ class ReflectionContext
195
196
// introduce misaligned pointers mapping between local and remote
196
197
// address space.
197
198
RangeStart = RangeStart & ~7 ;
198
- RangeEnd = RangeEnd + 7 & ~7 ;
199
+ RangeEnd = RangeEnd + 7 & ~7 ;
199
200
}
200
-
201
+
201
202
if (RangeStart == UINT64_MAX && RangeEnd == UINT64_MAX)
202
203
return false ;
203
204
@@ -386,116 +387,105 @@ class ReflectionContext
386
387
}
387
388
388
389
template <typename T> bool readELFSections (RemoteAddress ImageStart) {
389
- auto Buf =
390
+ auto HeaderBuf =
390
391
this ->getReader ().readBytes (ImageStart, sizeof (typename T::Header));
391
392
392
- auto Hdr = reinterpret_cast <const typename T::Header *>(Buf .get ());
393
+ auto Hdr = reinterpret_cast <const typename T::Header *>(HeaderBuf .get ());
393
394
assert (Hdr->getFileClass () == T::ELFClass && " invalid ELF file class" );
394
395
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);
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 ;
410
423
}
424
+ if (!MetadataSectionsPtrValue)
425
+ return false ;
411
426
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 ;
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
+ }
419
460
}
420
461
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 };
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));
450
468
};
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
-
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);
485
478
savedBuffers.push_back (std::move (Buf));
486
479
return true ;
487
480
}
488
-
481
+
489
482
bool readELF (RemoteAddress ImageStart) {
490
483
auto Buf =
491
484
this ->getReader ().readBytes (ImageStart, sizeof (llvm::ELF::Elf64_Ehdr));
492
-
493
485
// Read the header.
494
486
auto Hdr = reinterpret_cast <const llvm::ELF::Elf64_Ehdr *>(Buf.get ());
495
-
496
487
if (!Hdr->checkMagic ())
497
488
return false ;
498
-
499
489
// Check if we have a ELFCLASS32 or ELFCLASS64
500
490
unsigned char FileClass = Hdr->getFileClass ();
501
491
if (FileClass == llvm::ELF::ELFCLASS64) {
@@ -512,34 +502,34 @@ class ReflectionContext
512
502
auto Magic = this ->getReader ().readBytes (ImageStart, sizeof (uint32_t ));
513
503
if (!Magic)
514
504
return false ;
515
-
505
+
516
506
uint32_t MagicWord;
517
507
memcpy (&MagicWord, Magic.get (), sizeof (MagicWord));
518
-
508
+
519
509
// 32- and 64-bit Mach-O.
520
510
if (MagicWord == llvm::MachO::MH_MAGIC) {
521
511
return readMachOSections<MachOTraits<4 >>(ImageStart);
522
512
}
523
-
513
+
524
514
if (MagicWord == llvm::MachO::MH_MAGIC_64) {
525
515
return readMachOSections<MachOTraits<8 >>(ImageStart);
526
516
}
527
-
517
+
528
518
// PE. (This just checks for the DOS header; `readPECOFF` will further
529
519
// validate the existence of the PE header.)
530
520
auto MagicBytes = (const char *)Magic.get ();
531
521
if (MagicBytes[0 ] == ' M' && MagicBytes[1 ] == ' Z' ) {
532
522
return readPECOFF (ImageStart);
533
523
}
534
-
524
+
535
525
// ELF.
536
526
if (MagicBytes[0 ] == llvm::ELF::ElfMagic[0 ]
537
527
&& MagicBytes[1 ] == llvm::ELF::ElfMagic[1 ]
538
528
&& MagicBytes[2 ] == llvm::ELF::ElfMagic[2 ]
539
529
&& MagicBytes[3 ] == llvm::ELF::ElfMagic[3 ]) {
540
530
return readELF (ImageStart);
541
531
}
542
-
532
+
543
533
// We don't recognize the format.
544
534
return false ;
545
535
}
@@ -554,7 +544,7 @@ class ReflectionContext
554
544
return true ;
555
545
return ownsAddress (RemoteAddress (*MetadataAddress));
556
546
}
557
-
547
+
558
548
// / Returns true if the address falls within a registered image.
559
549
bool ownsAddress (RemoteAddress Address) {
560
550
for (auto Range : imageRanges) {
@@ -564,10 +554,10 @@ class ReflectionContext
564
554
&& Address.getAddressData () < End.getAddressData ())
565
555
return true ;
566
556
}
567
-
557
+
568
558
return false ;
569
559
}
570
-
560
+
571
561
// / Return a description of the layout of a class instance with the given
572
562
// / metadata as its isa pointer.
573
563
const TypeInfo *getMetadataTypeInfo (StoredPointer MetadataAddress) {
0 commit comments