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
@@ -238,18 +237,13 @@ class ReflectionContext
238
237
ReflStrMdSec.first == nullptr )
239
238
return false ;
240
239
241
- auto LocalStartAddress = reinterpret_cast <uint64_t >(SectBuf.get ());
242
- auto RemoteStartAddress = static_cast <uint64_t >(RangeStart);
243
-
244
240
ReflectionInfo info = {
245
241
{FieldMdSec.first , FieldMdSec.second },
246
242
{AssocTySec.first , AssocTySec.second },
247
243
{BuiltinTySec.first , BuiltinTySec.second },
248
244
{CaptureSec.first , CaptureSec.second },
249
245
{TypeRefMdSec.first , TypeRefMdSec.second },
250
- {ReflStrMdSec.first , ReflStrMdSec.second },
251
- LocalStartAddress,
252
- RemoteStartAddress};
246
+ {ReflStrMdSec.first , ReflStrMdSec.second }};
253
247
254
248
this ->addReflectionInfo (info);
255
249
@@ -347,19 +341,13 @@ class ReflectionContext
347
341
ReflStrMdSec.first == nullptr )
348
342
return false ;
349
343
350
- auto LocalStartAddress = reinterpret_cast <uintptr_t >(DOSHdrBuf.get ());
351
- auto RemoteStartAddress =
352
- static_cast <uintptr_t >(ImageStart.getAddressData ());
353
-
354
344
ReflectionInfo Info = {
355
345
{FieldMdSec.first , FieldMdSec.second },
356
346
{AssocTySec.first , AssocTySec.second },
357
347
{BuiltinTySec.first , BuiltinTySec.second },
358
348
{CaptureSec.first , CaptureSec.second },
359
349
{TypeRefMdSec.first , TypeRefMdSec.second },
360
- {ReflStrMdSec.first , ReflStrMdSec.second },
361
- LocalStartAddress,
362
- RemoteStartAddress};
350
+ {ReflStrMdSec.first , ReflStrMdSec.second }};
363
351
this ->addReflectionInfo (Info);
364
352
return true ;
365
353
}
@@ -387,105 +375,110 @@ class ReflectionContext
387
375
}
388
376
389
377
template <typename T> bool readELFSections (RemoteAddress ImageStart) {
390
- auto HeaderBuf =
378
+ auto Buf =
391
379
this ->getReader ().readBytes (ImageStart, sizeof (typename T::Header));
392
380
393
- auto Hdr = reinterpret_cast <const typename T::Header *>(HeaderBuf .get ());
381
+ auto Hdr = reinterpret_cast <const typename T::Header *>(Buf .get ());
394
382
assert (Hdr->getFileClass () == T::ELFClass && " invalid ELF file class" );
395
383
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 ;
384
+ // From the header, grab informations about the section header table.
385
+ auto SectionHdrAddress = ImageStart.getAddressData () + Hdr->e_shoff ;
386
+ auto SectionHdrNumEntries = Hdr->e_shnum ;
387
+ auto SectionEntrySize = Hdr->e_shentsize ;
388
+
389
+ // Collect all the section headers, we need them to look up the
390
+ // reflection sections (by name) and the string table.
391
+ std::vector<const typename T::Section *> SecHdrVec;
392
+ for (unsigned I = 0 ; I < SectionHdrNumEntries; ++I) {
393
+ auto SecBuf = this ->getReader ().readBytes (
394
+ RemoteAddress (SectionHdrAddress + (I * SectionEntrySize)),
395
+ SectionEntrySize);
396
+ auto SecHdr =
397
+ reinterpret_cast <const typename T::Section *>(SecBuf.get ());
398
+ SecHdrVec.push_back (SecHdr);
423
399
}
424
- if (!MetadataSectionsPtrValue)
425
- return false ;
426
400
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
- }
401
+ // This provides quick access to the section header string table index.
402
+ // We also here handle the unlikely even where the section index overflows
403
+ // and it's just a pointer to secondary storage (SHN_XINDEX).
404
+ uint32_t SecIdx = Hdr->e_shstrndx ;
405
+ if (SecIdx == llvm::ELF::SHN_XINDEX) {
406
+ assert (!SecHdrVec.empty () && " malformed ELF object" );
407
+ SecIdx = SecHdrVec[0 ]->sh_link ;
460
408
}
461
409
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));
410
+ assert (SecIdx < SecHdrVec.size () && " malformed ELF object" );
411
+
412
+ const typename T::Section *SecHdrStrTab = SecHdrVec[SecIdx];
413
+ typename T::Offset StrTabOffset = SecHdrStrTab->sh_offset ;
414
+ typename T::Size StrTabSize = SecHdrStrTab->sh_size ;
415
+
416
+ auto StrTabStart =
417
+ RemoteAddress (ImageStart.getAddressData () + StrTabOffset);
418
+ auto StrTabBuf = this ->getReader ().readBytes (StrTabStart, StrTabSize);
419
+ auto StrTab = reinterpret_cast <const char *>(StrTabBuf.get ());
420
+
421
+ auto findELFSectionByName = [&](std::string Name)
422
+ -> std::pair<RemoteRef<void >, uint64_t > {
423
+ // Now for all the sections, find their name.
424
+ for (const typename T::Section *Hdr : SecHdrVec) {
425
+ uint32_t Offset = Hdr->sh_name ;
426
+ auto SecName = std::string (StrTab + Offset);
427
+ if (SecName != Name)
428
+ continue ;
429
+ auto SecStart =
430
+ RemoteAddress (ImageStart.getAddressData () + Hdr->sh_addr );
431
+ auto SecSize = Hdr->sh_size ;
432
+ auto SecBuf = this ->getReader ().readBytes (SecStart, SecSize);
433
+ auto SecContents = RemoteRef<void >(SecStart.getAddressData (),
434
+ SecBuf.get ());
435
+ savedBuffers.push_back (std::move (SecBuf));
436
+ return {SecContents, SecSize};
437
+ }
438
+ return {nullptr , 0 };
468
439
};
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);
440
+
441
+ auto FieldMdSec = findELFSectionByName (" swift5_fieldmd" );
442
+ auto AssocTySec = findELFSectionByName (" swift5_assocty" );
443
+ auto BuiltinTySec = findELFSectionByName (" swift5_builtin" );
444
+ auto CaptureSec = findELFSectionByName (" swift5_capture" );
445
+ auto TypeRefMdSec = findELFSectionByName (" swift5_typeref" );
446
+ auto ReflStrMdSec = findELFSectionByName (" swift5_reflstr" );
447
+
448
+ // We succeed if at least one of the sections is present in the
449
+ // ELF executable.
450
+ if (FieldMdSec.first == nullptr &&
451
+ AssocTySec.first == nullptr &&
452
+ BuiltinTySec.first == nullptr &&
453
+ CaptureSec.first == nullptr &&
454
+ TypeRefMdSec.first == nullptr &&
455
+ ReflStrMdSec.first == nullptr )
456
+ return false ;
457
+
458
+ ReflectionInfo info = {
459
+ {FieldMdSec.first , FieldMdSec.second },
460
+ {AssocTySec.first , AssocTySec.second },
461
+ {BuiltinTySec.first , BuiltinTySec.second },
462
+ {CaptureSec.first , CaptureSec.second },
463
+ {TypeRefMdSec.first , TypeRefMdSec.second },
464
+ {ReflStrMdSec.first , ReflStrMdSec.second }};
465
+
466
+ this ->addReflectionInfo (info);
467
+
478
468
savedBuffers.push_back (std::move (Buf));
479
469
return true ;
480
470
}
481
-
471
+
482
472
bool readELF (RemoteAddress ImageStart) {
483
473
auto Buf =
484
474
this ->getReader ().readBytes (ImageStart, sizeof (llvm::ELF::Elf64_Ehdr));
475
+
485
476
// Read the header.
486
477
auto Hdr = reinterpret_cast <const llvm::ELF::Elf64_Ehdr *>(Buf.get ());
478
+
487
479
if (!Hdr->checkMagic ())
488
480
return false ;
481
+
489
482
// Check if we have a ELFCLASS32 or ELFCLASS64
490
483
unsigned char FileClass = Hdr->getFileClass ();
491
484
if (FileClass == llvm::ELF::ELFCLASS64) {
@@ -502,34 +495,34 @@ class ReflectionContext
502
495
auto Magic = this ->getReader ().readBytes (ImageStart, sizeof (uint32_t ));
503
496
if (!Magic)
504
497
return false ;
505
-
498
+
506
499
uint32_t MagicWord;
507
500
memcpy (&MagicWord, Magic.get (), sizeof (MagicWord));
508
-
501
+
509
502
// 32- and 64-bit Mach-O.
510
503
if (MagicWord == llvm::MachO::MH_MAGIC) {
511
504
return readMachOSections<MachOTraits<4 >>(ImageStart);
512
505
}
513
-
506
+
514
507
if (MagicWord == llvm::MachO::MH_MAGIC_64) {
515
508
return readMachOSections<MachOTraits<8 >>(ImageStart);
516
509
}
517
-
510
+
518
511
// PE. (This just checks for the DOS header; `readPECOFF` will further
519
512
// validate the existence of the PE header.)
520
513
auto MagicBytes = (const char *)Magic.get ();
521
514
if (MagicBytes[0 ] == ' M' && MagicBytes[1 ] == ' Z' ) {
522
515
return readPECOFF (ImageStart);
523
516
}
524
-
517
+
525
518
// ELF.
526
519
if (MagicBytes[0 ] == llvm::ELF::ElfMagic[0 ]
527
520
&& MagicBytes[1 ] == llvm::ELF::ElfMagic[1 ]
528
521
&& MagicBytes[2 ] == llvm::ELF::ElfMagic[2 ]
529
522
&& MagicBytes[3 ] == llvm::ELF::ElfMagic[3 ]) {
530
523
return readELF (ImageStart);
531
524
}
532
-
525
+
533
526
// We don't recognize the format.
534
527
return false ;
535
528
}
@@ -544,7 +537,7 @@ class ReflectionContext
544
537
return true ;
545
538
return ownsAddress (RemoteAddress (*MetadataAddress));
546
539
}
547
-
540
+
548
541
// / Returns true if the address falls within a registered image.
549
542
bool ownsAddress (RemoteAddress Address) {
550
543
for (auto Range : imageRanges) {
@@ -554,10 +547,10 @@ class ReflectionContext
554
547
&& Address.getAddressData () < End.getAddressData ())
555
548
return true ;
556
549
}
557
-
550
+
558
551
return false ;
559
552
}
560
-
553
+
561
554
// / Return a description of the layout of a class instance with the given
562
555
// / metadata as its isa pointer.
563
556
const TypeInfo *getMetadataTypeInfo (StoredPointer MetadataAddress) {
0 commit comments