Skip to content

Commit 4158517

Browse files
authored
Merge pull request #17771 from dcci/remotemirrorself
2 parents 08ec1ba + e9d8e0a commit 4158517

File tree

2 files changed

+110
-6
lines changed

2 files changed

+110
-6
lines changed

include/swift/Reflection/ReflectionContext.h

Lines changed: 110 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
#define SWIFT_REFLECTION_REFLECTIONCONTEXT_H
2020

2121
#include "llvm/BinaryFormat/MachO.h"
22+
#include "llvm/BinaryFormat/ELF.h"
23+
2224
#include "swift/Remote/MemoryReader.h"
2325
#include "swift/Remote/MetadataReader.h"
2426
#include "swift/Reflection/Records.h"
@@ -227,8 +229,114 @@ class ReflectionContext
227229
return readMachOSections<MachOTraits<8>>(ImageStart);
228230
return false;
229231
}
230-
#endif // defined(__APPLE__) && defined(__MACH__)
231-
232+
#else // ELF platforms.
233+
bool addImage(RemoteAddress ImageStart) {
234+
auto Buf =
235+
this->getReader().readBytes(ImageStart, sizeof(llvm::ELF::Elf64_Ehdr));
236+
237+
// Read the header.
238+
auto Hdr = reinterpret_cast<const llvm::ELF::Elf64_Ehdr *>(Buf.get());
239+
240+
if (!Hdr->checkMagic())
241+
return false;
242+
243+
// From the header, grab informations about the section header table.
244+
auto SectionHdrAddress = ImageStart.getAddressData() + Hdr->e_shoff;
245+
auto SectionHdrNumEntries = Hdr->e_shnum;
246+
auto SectionEntrySize = Hdr->e_shentsize;
247+
248+
// Collect all the section headers, we need them to look up the
249+
// reflection sections (by name) and the string table.
250+
std::vector<const llvm::ELF::Elf64_Shdr *> SecHdrVec;
251+
for (unsigned I = 0; I < SectionHdrNumEntries; ++I) {
252+
auto SecBuf = this->getReader().readBytes(
253+
RemoteAddress(SectionHdrAddress + (I * SectionEntrySize)),
254+
SectionEntrySize);
255+
auto SecHdr =
256+
reinterpret_cast<const llvm::ELF::Elf64_Shdr *>(SecBuf.get());
257+
SecHdrVec.push_back(SecHdr);
258+
}
259+
260+
// This provides quick access to the section header string table index.
261+
// We also here handle the unlikely even where the section index overflows
262+
// and it's just a pointer to secondary storage (SHN_XINDEX).
263+
uint32_t SecIdx = Hdr->e_shstrndx;
264+
if (SecIdx == llvm::ELF::SHN_XINDEX) {
265+
assert(!SecHdrVec.empty() && "malformed ELF object");
266+
SecIdx = SecHdrVec[0]->sh_link;
267+
}
268+
269+
assert(SecIdx < SecHdrVec.size() && "malformed ELF object");
270+
271+
const llvm::ELF::Elf64_Shdr *SecHdrStrTab = SecHdrVec[SecIdx];
272+
llvm::ELF::Elf64_Off StrTabOffset = SecHdrStrTab->sh_offset;
273+
llvm::ELF::Elf64_Xword StrTabSize = SecHdrStrTab->sh_size;
274+
275+
auto StrTabStart =
276+
RemoteAddress(ImageStart.getAddressData() + StrTabOffset);
277+
auto StrTabBuf = this->getReader().readBytes(StrTabStart, StrTabSize);
278+
auto StrTab = reinterpret_cast<const char *>(StrTabBuf.get());
279+
280+
auto findELFSectionByName = [&](std::string Name)
281+
-> std::pair<std::pair<const char *, const char *>, uint32_t> {
282+
// Now for all the sections, find their name.
283+
for (const llvm::ELF::Elf64_Shdr *Hdr : SecHdrVec) {
284+
uint32_t Offset = Hdr->sh_name;
285+
auto SecName = std::string(StrTab + Offset);
286+
if (SecName != Name)
287+
continue;
288+
auto SecStart =
289+
RemoteAddress(ImageStart.getAddressData() + Hdr->sh_offset);
290+
auto SecSize = Hdr->sh_size;
291+
auto SecBuf = this->getReader().readBytes(SecStart, SecSize);
292+
auto SecContents = reinterpret_cast<const char *>(SecBuf.get());
293+
return {{SecContents, SecContents + SecSize},
294+
Hdr->sh_addr - Hdr->sh_offset};
295+
}
296+
return {{nullptr, nullptr}, 0};
297+
};
298+
299+
auto FieldMdSec = findELFSectionByName("swift5_fieldmd");
300+
auto AssocTySec = findELFSectionByName("swift5_assocty");
301+
auto BuiltinTySec = findELFSectionByName("swift5_builtin");
302+
auto CaptureSec = findELFSectionByName("swift5_capture");
303+
auto TypeRefMdSec = findELFSectionByName("swift5_typeref");
304+
auto ReflStrMdSec = findELFSectionByName("swift5_reflstr");
305+
306+
// We succeed if at least one of the sections is present in the
307+
// ELF executable.
308+
if (FieldMdSec.first.first == nullptr &&
309+
AssocTySec.first.first == nullptr &&
310+
BuiltinTySec.first.first == nullptr &&
311+
CaptureSec.first.first == nullptr &&
312+
TypeRefMdSec.first.first == nullptr &&
313+
ReflStrMdSec.first.first == nullptr)
314+
return false;
315+
316+
auto LocalStartAddress = reinterpret_cast<uintptr_t>(Buf.get());
317+
auto RemoteStartAddress =
318+
static_cast<uintptr_t>(ImageStart.getAddressData());
319+
320+
ReflectionInfo info = {
321+
{{FieldMdSec.first.first, FieldMdSec.first.second}, FieldMdSec.second},
322+
{{AssocTySec.first.first, AssocTySec.first.second}, AssocTySec.second},
323+
{{BuiltinTySec.first.first, BuiltinTySec.first.second},
324+
BuiltinTySec.second},
325+
{{CaptureSec.first.first, CaptureSec.first.second}, CaptureSec.second},
326+
{{TypeRefMdSec.first.first, TypeRefMdSec.first.second},
327+
TypeRefMdSec.second},
328+
{{ReflStrMdSec.first.first, ReflStrMdSec.first.second},
329+
ReflStrMdSec.second},
330+
LocalStartAddress,
331+
RemoteStartAddress};
332+
333+
this->addReflectionInfo(info);
334+
335+
savedBuffers.push_back(std::move(Buf));
336+
return true;
337+
}
338+
#endif
339+
232340
void addReflectionInfo(ReflectionInfo I) {
233341
getBuilder().addReflectionInfo(I);
234342
}

tools/swift-reflection-dump/swift-reflection-dump.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -263,12 +263,8 @@ static int doDumpReflectionSections(ArrayRef<std::string> binaryFilenames,
263263
objectOwners.push_back(std::move(objectOwner));
264264
objectFiles.push_back(objectFile);
265265

266-
#if defined(__APPLE__)
267266
auto startAddress = (uintptr_t)objectFile->getData().begin();
268267
context.addImage(RemoteAddress(startAddress));
269-
#else
270-
context.addReflectionInfo(findReflectionInfo(objectFile));
271-
#endif
272268
}
273269

274270
switch (action) {

0 commit comments

Comments
 (0)