|
19 | 19 | #define SWIFT_REFLECTION_REFLECTIONCONTEXT_H
|
20 | 20 |
|
21 | 21 | #include "llvm/BinaryFormat/MachO.h"
|
| 22 | +#include "llvm/BinaryFormat/ELF.h" |
| 23 | + |
22 | 24 | #include "swift/Remote/MemoryReader.h"
|
23 | 25 | #include "swift/Remote/MetadataReader.h"
|
24 | 26 | #include "swift/Reflection/Records.h"
|
@@ -227,8 +229,114 @@ class ReflectionContext
|
227 | 229 | return readMachOSections<MachOTraits<8>>(ImageStart);
|
228 | 230 | return false;
|
229 | 231 | }
|
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 | + |
232 | 340 | void addReflectionInfo(ReflectionInfo I) {
|
233 | 341 | getBuilder().addReflectionInfo(I);
|
234 | 342 | }
|
|
0 commit comments