Skip to content

Commit 8db9006

Browse files
committed
Revert "Fix parsing of ELF images"
This reverts commit e2b6a3d. This broke on the handling of x86_64 relocation as well as the Windows build process.
1 parent 40016b5 commit 8db9006

File tree

3 files changed

+118
-208
lines changed

3 files changed

+118
-208
lines changed

include/swift/Reflection/ReflectionContext.h

Lines changed: 105 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
#include "swift/Reflection/TypeRef.h"
3131
#include "swift/Reflection/TypeRefBuilder.h"
3232
#include "swift/Runtime/Unreachable.h"
33-
#include "../../../stdlib/public/runtime/ImageInspectionELF.h"
3433

3534
#include <iostream>
3635
#include <set>
@@ -60,15 +59,15 @@ template <unsigned char ELFClass> struct ELFTraits;
6059

6160
template <> struct ELFTraits<llvm::ELF::ELFCLASS32> {
6261
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;
6463
using Offset = llvm::ELF::Elf32_Off;
6564
using Size = llvm::ELF::Elf32_Word;
6665
static constexpr unsigned char ELFClass = llvm::ELF::ELFCLASS32;
6766
};
6867

6968
template <> struct ELFTraits<llvm::ELF::ELFCLASS64> {
7069
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;
7271
using Offset = llvm::ELF::Elf64_Off;
7372
using Size = llvm::ELF::Elf64_Xword;
7473
static constexpr unsigned char ELFClass = llvm::ELF::ELFCLASS64;
@@ -113,7 +112,7 @@ class ReflectionContext
113112

114113
ReflectionContext(const ReflectionContext &other) = delete;
115114
ReflectionContext &operator=(const ReflectionContext &other) = delete;
116-
115+
117116
MemoryReader &getReader() {
118117
return *this->Reader;
119118
}
@@ -196,9 +195,9 @@ class ReflectionContext
196195
// introduce misaligned pointers mapping between local and remote
197196
// address space.
198197
RangeStart = RangeStart & ~7;
199-
RangeEnd = RangeEnd + 7 & ~7;
198+
RangeEnd = RangeEnd + 7 & ~7;
200199
}
201-
200+
202201
if (RangeStart == UINT64_MAX && RangeEnd == UINT64_MAX)
203202
return false;
204203

@@ -387,105 +386,116 @@ class ReflectionContext
387386
}
388387

389388
template <typename T> bool readELFSections(RemoteAddress ImageStart) {
390-
auto HeaderBuf =
389+
auto Buf =
391390
this->getReader().readBytes(ImageStart, sizeof(typename T::Header));
392391

393-
auto Hdr = reinterpret_cast<const typename T::Header *>(HeaderBuf.get());
392+
auto Hdr = reinterpret_cast<const typename T::Header *>(Buf.get());
394393
assert(Hdr->getFileClass() == T::ELFClass && "invalid ELF file class");
395394

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);
423410
}
424-
if (!MetadataSectionsPtrValue)
425-
return false;
426411

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;
460419
}
461420

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};
468450
};
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+
478485
savedBuffers.push_back(std::move(Buf));
479486
return true;
480487
}
481-
488+
482489
bool readELF(RemoteAddress ImageStart) {
483490
auto Buf =
484491
this->getReader().readBytes(ImageStart, sizeof(llvm::ELF::Elf64_Ehdr));
492+
485493
// Read the header.
486494
auto Hdr = reinterpret_cast<const llvm::ELF::Elf64_Ehdr *>(Buf.get());
495+
487496
if (!Hdr->checkMagic())
488497
return false;
498+
489499
// Check if we have a ELFCLASS32 or ELFCLASS64
490500
unsigned char FileClass = Hdr->getFileClass();
491501
if (FileClass == llvm::ELF::ELFCLASS64) {
@@ -502,34 +512,34 @@ class ReflectionContext
502512
auto Magic = this->getReader().readBytes(ImageStart, sizeof(uint32_t));
503513
if (!Magic)
504514
return false;
505-
515+
506516
uint32_t MagicWord;
507517
memcpy(&MagicWord, Magic.get(), sizeof(MagicWord));
508-
518+
509519
// 32- and 64-bit Mach-O.
510520
if (MagicWord == llvm::MachO::MH_MAGIC) {
511521
return readMachOSections<MachOTraits<4>>(ImageStart);
512522
}
513-
523+
514524
if (MagicWord == llvm::MachO::MH_MAGIC_64) {
515525
return readMachOSections<MachOTraits<8>>(ImageStart);
516526
}
517-
527+
518528
// PE. (This just checks for the DOS header; `readPECOFF` will further
519529
// validate the existence of the PE header.)
520530
auto MagicBytes = (const char*)Magic.get();
521531
if (MagicBytes[0] == 'M' && MagicBytes[1] == 'Z') {
522532
return readPECOFF(ImageStart);
523533
}
524-
534+
525535
// ELF.
526536
if (MagicBytes[0] == llvm::ELF::ElfMagic[0]
527537
&& MagicBytes[1] == llvm::ELF::ElfMagic[1]
528538
&& MagicBytes[2] == llvm::ELF::ElfMagic[2]
529539
&& MagicBytes[3] == llvm::ELF::ElfMagic[3]) {
530540
return readELF(ImageStart);
531541
}
532-
542+
533543
// We don't recognize the format.
534544
return false;
535545
}
@@ -544,7 +554,7 @@ class ReflectionContext
544554
return true;
545555
return ownsAddress(RemoteAddress(*MetadataAddress));
546556
}
547-
557+
548558
/// Returns true if the address falls within a registered image.
549559
bool ownsAddress(RemoteAddress Address) {
550560
for (auto Range : imageRanges) {
@@ -554,10 +564,10 @@ class ReflectionContext
554564
&& Address.getAddressData() < End.getAddressData())
555565
return true;
556566
}
557-
567+
558568
return false;
559569
}
560-
570+
561571
/// Return a description of the layout of a class instance with the given
562572
/// metadata as its isa pointer.
563573
const TypeInfo *getMetadataTypeInfo(StoredPointer MetadataAddress) {

stdlib/public/runtime/ImageInspectionELF.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121

2222
#define SWIFT_REFLECTION_METADATA_ELF_NOTE_MAGIC_STRING "swift_reflection_metadata_magic_string"
2323

24+
#if defined(__ELF__)
25+
2426
#include "../SwiftShims/Visibility.h"
2527
#include <cstdint>
2628
#include <cstddef>
@@ -59,10 +61,10 @@ struct MetadataSections {
5961
};
6062
} // namespace swift
6163

62-
#if defined(__ELF__)
6364
// Called by injected constructors when a dynamic library is loaded.
6465
SWIFT_RUNTIME_EXPORT
6566
void swift_addNewDSOImage(const void *addr);
67+
6668
#endif // defined(__ELF__)
6769

6870
#endif // SWIFT_RUNTIME_IMAGE_INSPECTION_ELF_H

0 commit comments

Comments
 (0)