22
22
#include " llvm/BinaryFormat/MachO.h"
23
23
#include " llvm/BinaryFormat/ELF.h"
24
24
#include " llvm/Object/COFF.h"
25
+ #include " llvm/Support/Memory.h"
25
26
26
27
#include " swift/ABI/Enum.h"
27
28
#include " swift/ABI/ObjectFile.h"
@@ -393,29 +394,60 @@ class ReflectionContext
393
394
return readPECOFFSections (ImageStart);
394
395
}
395
396
396
- template <typename T> bool readELFSections (RemoteAddress ImageStart) {
397
- auto Buf =
398
- this ->getReader ().readBytes (ImageStart, sizeof (typename T::Header));
397
+ template <typename T>
398
+ bool readELFSections (RemoteAddress ImageStart,
399
+ llvm::Optional<llvm::sys::MemoryBlock> FileBuffer) {
400
+ // When reading from the FileBuffer we can simply return a pointer to
401
+ // the underlying data.
402
+ // When reading from the process, we need to keep the memory around
403
+ // until the end of the function, so we store it inside ReadDataBuffer.
404
+ // We do this so in both cases we can return a simple pointer.
405
+ std::vector<MemoryReader::ReadBytesResult> ReadDataBuffer;
406
+ auto readData = [&](uint64_t Offset, uint64_t Size) -> const void * {
407
+ if (FileBuffer.hasValue ()) {
408
+ auto Buffer = FileBuffer.getValue ();
409
+ if (Offset + Size > Buffer.allocatedSize ())
410
+ return nullptr ;
411
+ return (const void *)((uint64_t )Buffer.base () + Offset);
412
+ } else {
413
+ MemoryReader::ReadBytesResult Buf =
414
+ this ->getReader ().readBytes (ImageStart + Offset, Size);
415
+ if (!Buf)
416
+ return nullptr ;
417
+ ReadDataBuffer.push_back (std::move (Buf));
418
+ return ReadDataBuffer.back ().get ();
419
+ }
420
+ };
399
421
400
- auto Hdr = reinterpret_cast <const typename T::Header *>(Buf.get ());
422
+ const void *Buf = readData (0 , sizeof (typename T::Header));
423
+ if (!Buf)
424
+ return false ;
425
+ auto Hdr = reinterpret_cast <const typename T::Header *>(Buf);
401
426
assert (Hdr->getFileClass () == T::ELFClass && " invalid ELF file class" );
402
427
403
- // From the header, grab informations about the section header table.
404
- auto SectionHdrAddress = ImageStart.getAddressData () + Hdr->e_shoff ;
405
- auto SectionHdrNumEntries = Hdr->e_shnum ;
406
- auto SectionEntrySize = Hdr->e_shentsize ;
428
+ // From the header, grab information about the section header table.
429
+ uint64_t SectionHdrAddress = Hdr->e_shoff ;
430
+ uint16_t SectionHdrNumEntries = Hdr->e_shnum ;
431
+ uint16_t SectionEntrySize = Hdr->e_shentsize ;
432
+
433
+ if (sizeof (typename T::Section) > SectionEntrySize)
434
+ return false ;
435
+ if (SectionHdrNumEntries == 0 )
436
+ return false ;
407
437
408
438
// Collect all the section headers, we need them to look up the
409
439
// reflection sections (by name) and the string table.
440
+ // We read the section headers from the FileBuffer, since they are
441
+ // not mapped in the child process.
410
442
std::vector<const typename T::Section *> SecHdrVec;
411
443
for (unsigned I = 0 ; I < SectionHdrNumEntries; ++I) {
412
- auto SecBuf = this ->getReader ().readBytes (
413
- RemoteAddress (SectionHdrAddress + (I * SectionEntrySize)),
414
- SectionEntrySize);
444
+ uint64_t Offset = SectionHdrAddress + (I * SectionEntrySize);
445
+ auto SecBuf = readData (Offset, sizeof (typename T::Section));
415
446
if (!SecBuf)
416
447
return false ;
417
- auto SecHdr =
418
- reinterpret_cast <const typename T::Section *>(SecBuf.get ());
448
+ const typename T::Section *SecHdr =
449
+ reinterpret_cast <const typename T::Section *>(SecBuf);
450
+
419
451
SecHdrVec.push_back (SecHdr);
420
452
}
421
453
@@ -434,30 +466,54 @@ class ReflectionContext
434
466
typename T::Offset StrTabOffset = SecHdrStrTab->sh_offset ;
435
467
typename T::Size StrTabSize = SecHdrStrTab->sh_size ;
436
468
437
- auto StrTabStart =
438
- RemoteAddress (ImageStart.getAddressData () + StrTabOffset);
439
- auto StrTabBuf = this ->getReader ().readBytes (StrTabStart, StrTabSize);
440
- auto StrTab = reinterpret_cast <const char *>(StrTabBuf.get ());
441
-
442
- auto findELFSectionByName = [&](llvm::StringRef Name)
443
- -> std::pair<RemoteRef<void >, uint64_t > {
444
- // Now for all the sections, find their name.
445
- for (const typename T::Section *Hdr : SecHdrVec) {
446
- uint32_t Offset = Hdr->sh_name ;
447
- auto SecName = std::string (StrTab + Offset);
448
- if (SecName != Name)
449
- continue ;
450
- auto SecStart =
451
- RemoteAddress (ImageStart.getAddressData () + Hdr->sh_addr );
452
- auto SecSize = Hdr->sh_size ;
453
- auto SecBuf = this ->getReader ().readBytes (SecStart, SecSize);
454
- auto SecContents = RemoteRef<void >(SecStart.getAddressData (),
455
- SecBuf.get ());
456
- savedBuffers.push_back (std::move (SecBuf));
457
- return {SecContents, SecSize};
458
- }
459
- return {nullptr , 0 };
460
- };
469
+ auto StrTabBuf = readData (StrTabOffset, StrTabSize);
470
+ if (!StrTabBuf)
471
+ return false ;
472
+ auto StrTab = reinterpret_cast <const char *>(StrTabBuf);
473
+ bool Error = false ;
474
+ auto findELFSectionByName =
475
+ [&](llvm::StringRef Name) -> std::pair<RemoteRef<void >, uint64_t > {
476
+ if (Error)
477
+ return {nullptr , 0 };
478
+ // Now for all the sections, find their name.
479
+ for (const typename T::Section *Hdr : SecHdrVec) {
480
+ uint32_t Offset = Hdr->sh_name ;
481
+ const char *Start = (const char *)StrTab + Offset;
482
+ uint64_t Size = strnlen (Start, StrTabSize - Offset);
483
+ if (Size > StrTabSize - Offset) {
484
+ Error = true ;
485
+ break ;
486
+ }
487
+ std::string SecName (Start, Size);
488
+ if (SecName != Name)
489
+ continue ;
490
+ RemoteAddress SecStart =
491
+ RemoteAddress (ImageStart.getAddressData () + Hdr->sh_addr );
492
+ auto SecSize = Hdr->sh_size ;
493
+ MemoryReader::ReadBytesResult SecBuf;
494
+ if (FileBuffer.hasValue ()) {
495
+ // sh_offset gives us the offset to the section in the file,
496
+ // while sh_addr gives us the offset in the process.
497
+ auto Offset = Hdr->sh_offset ;
498
+ if (FileBuffer->allocatedSize () > Offset + Size) {
499
+ Error = true ;
500
+ break ;
501
+ }
502
+ auto *Buf = malloc (SecSize);
503
+ SecBuf = MemoryReader::ReadBytesResult (
504
+ Buf, [](const void *ptr) { free (const_cast <void *>(ptr)); });
505
+ memcpy ((void *)Buf,
506
+ (const void *)((uint64_t )FileBuffer->base () + Offset), Size);
507
+ } else {
508
+ SecBuf = this ->getReader ().readBytes (SecStart, SecSize);
509
+ }
510
+ auto SecContents =
511
+ RemoteRef<void >(SecStart.getAddressData (), SecBuf.get ());
512
+ savedBuffers.push_back (std::move (SecBuf));
513
+ return {SecContents, SecSize};
514
+ }
515
+ return {nullptr , 0 };
516
+ };
461
517
462
518
SwiftObjectFileFormatELF ObjectFileFormat;
463
519
auto FieldMdSec = findELFSectionByName (
@@ -473,6 +529,9 @@ class ReflectionContext
473
529
auto ReflStrMdSec = findELFSectionByName (
474
530
ObjectFileFormat.getSectionName (ReflectionSectionKind::reflstr));
475
531
532
+ if (Error)
533
+ return false ;
534
+
476
535
// We succeed if at least one of the sections is present in the
477
536
// ELF executable.
478
537
if (FieldMdSec.first == nullptr &&
@@ -492,12 +551,28 @@ class ReflectionContext
492
551
{ReflStrMdSec.first , ReflStrMdSec.second }};
493
552
494
553
this ->addReflectionInfo (info);
495
-
496
- savedBuffers.push_back (std::move (Buf));
497
554
return true ;
498
555
}
499
-
500
- bool readELF (RemoteAddress ImageStart) {
556
+
557
+ // / Parses metadata information from an ELF image. Because the Section
558
+ // / Header Table maybe be missing (for example, when reading from a
559
+ // / process) this method optionally receives a buffer with the contents
560
+ // / of the image's file, from where it will the necessary information.
561
+ // /
562
+ // /
563
+ // / \param[in] ImageStart
564
+ // / A remote address pointing to the start of the image in the running
565
+ // / process.
566
+ // /
567
+ // / \param[in] FileBuffer
568
+ // / A buffer which contains the contents of the image's file
569
+ // / in disk. If missing, all the information will be read using the
570
+ // / instance's memory reader.
571
+ // /
572
+ // / \return
573
+ // / /b True if the metadata information was parsed successfully,
574
+ // / /b false otherwise.
575
+ bool readELF (RemoteAddress ImageStart, llvm::Optional<llvm::sys::MemoryBlock> FileBuffer) {
501
576
auto Buf =
502
577
this ->getReader ().readBytes (ImageStart, sizeof (llvm::ELF::Elf64_Ehdr));
503
578
@@ -510,9 +585,11 @@ class ReflectionContext
510
585
// Check if we have a ELFCLASS32 or ELFCLASS64
511
586
unsigned char FileClass = Hdr->getFileClass ();
512
587
if (FileClass == llvm::ELF::ELFCLASS64) {
513
- return readELFSections<ELFTraits<llvm::ELF::ELFCLASS64>>(ImageStart);
588
+ return readELFSections<ELFTraits<llvm::ELF::ELFCLASS64>>(
589
+ ImageStart, FileBuffer);
514
590
} else if (FileClass == llvm::ELF::ELFCLASS32) {
515
- return readELFSections<ELFTraits<llvm::ELF::ELFCLASS32>>(ImageStart);
591
+ return readELFSections<ELFTraits<llvm::ELF::ELFCLASS32>>(
592
+ ImageStart, FileBuffer);
516
593
} else {
517
594
return false ;
518
595
}
@@ -542,15 +619,16 @@ class ReflectionContext
542
619
if (MagicBytes[0 ] == ' M' && MagicBytes[1 ] == ' Z' ) {
543
620
return readPECOFF (ImageStart);
544
621
}
545
-
622
+
623
+
546
624
// ELF.
547
625
if (MagicBytes[0 ] == llvm::ELF::ElfMagic[0 ]
548
626
&& MagicBytes[1 ] == llvm::ELF::ElfMagic[1 ]
549
627
&& MagicBytes[2 ] == llvm::ELF::ElfMagic[2 ]
550
628
&& MagicBytes[3 ] == llvm::ELF::ElfMagic[3 ]) {
551
- return readELF (ImageStart);
629
+ return readELF (ImageStart, llvm::Optional<llvm::sys::MemoryBlock>() );
552
630
}
553
-
631
+
554
632
// We don't recognize the format.
555
633
return false ;
556
634
}
0 commit comments