@@ -687,19 +687,93 @@ DeviceBinaryImage::getProperty(const char *PropName) const {
687
687
return *It;
688
688
}
689
689
690
+ // Reads an integer value from ELF data.
691
+ template <typename ResT>
692
+ static ResT readELFValue (const unsigned char *Data, size_t NumBytes,
693
+ bool IsBigEndian) {
694
+ assert (NumBytes <= sizeof (ResT));
695
+ ResT Result = 0 ;
696
+ if (IsBigEndian) {
697
+ for (size_t I = 0 ; I < NumBytes; ++I) {
698
+ Result = (Result << 8 ) | static_cast <ResT>(Data[I]);
699
+ }
700
+ } else {
701
+ std::copy (Data, Data + NumBytes, reinterpret_cast <char *>(&Result));
702
+ }
703
+ return Result;
704
+ }
705
+
706
+ // Checks if an ELF image contains a section with a specified name.
707
+ static bool checkELFSectionPresent (const std::string &ExpectedSectionName,
708
+ const unsigned char *ImgData,
709
+ size_t ImgSize) {
710
+ // Check for 64bit and big-endian.
711
+ bool Is64bit = ImgData[4 ] == 2 ;
712
+ bool IsBigEndian = ImgData[5 ] == 2 ;
713
+
714
+ // Make offsets based on whether the ELF file is 64bit or not.
715
+ size_t SectionHeaderOffsetInfoOffset = Is64bit ? 0x28 : 0x20 ;
716
+ size_t SectionHeaderSizeInfoOffset = Is64bit ? 0x3A : 0x2E ;
717
+ size_t SectionHeaderNumInfoOffset = Is64bit ? 0x3C : 0x30 ;
718
+ size_t SectionStringsHeaderIndexInfoOffset = Is64bit ? 0x3E : 0x32 ;
719
+
720
+ // if the image doesn't contain enough data for the header values, end early.
721
+ if (ImgSize < SectionStringsHeaderIndexInfoOffset + 2 )
722
+ return false ;
723
+
724
+ // Read the e_shoff, e_shentsize, e_shnum, and e_shstrndx entries in the
725
+ // header.
726
+ uint64_t SectionHeaderOffset = readELFValue<uint64_t >(
727
+ ImgData + SectionHeaderOffsetInfoOffset, Is64bit ? 8 : 4 , IsBigEndian);
728
+ uint16_t SectionHeaderSize = readELFValue<uint16_t >(
729
+ ImgData + SectionHeaderSizeInfoOffset, 2 , IsBigEndian);
730
+ uint16_t SectionHeaderNum = readELFValue<uint16_t >(
731
+ ImgData + SectionHeaderNumInfoOffset, 2 , IsBigEndian);
732
+ uint16_t SectionStringsHeaderIndex = readELFValue<uint16_t >(
733
+ ImgData + SectionStringsHeaderIndexInfoOffset, 2 , IsBigEndian);
734
+
735
+ // End early if we do not have the expected number of section headers or
736
+ // if the read section string header index is out-of-range.
737
+ if (ImgSize < SectionHeaderOffset + SectionHeaderNum * SectionHeaderSize ||
738
+ SectionStringsHeaderIndex >= SectionHeaderNum)
739
+ return false ;
740
+
741
+ // Get the location of the section string data.
742
+ size_t SectionStringsInfoOffset = Is64bit ? 0x18 : 0x10 ;
743
+ const unsigned char *SectionStringsHeaderData =
744
+ ImgData + SectionHeaderOffset +
745
+ SectionStringsHeaderIndex * SectionHeaderSize;
746
+ uint64_t SectionStrings = readELFValue<uint64_t >(
747
+ SectionStringsHeaderData + SectionStringsInfoOffset, Is64bit ? 8 : 4 ,
748
+ IsBigEndian);
749
+ const unsigned char *SectionStringsData = ImgData + SectionStrings;
750
+
751
+ // For each section, check the name against the expected section and return
752
+ // true if we find it.
753
+ for (size_t I = 0 ; I < SectionHeaderNum; ++I) {
754
+ // Get the offset into the section string data of this sections name.
755
+ const unsigned char *HeaderData =
756
+ ImgData + SectionHeaderOffset + I * SectionHeaderSize;
757
+ uint32_t SectionNameOffset =
758
+ readELFValue<uint32_t >(HeaderData, 4 , IsBigEndian);
759
+
760
+ // Read the section name and check if it is the same as the name we are
761
+ // looking for.
762
+ const char *SectionName =
763
+ reinterpret_cast <const char *>(SectionStringsData + SectionNameOffset);
764
+ if (SectionName == ExpectedSectionName)
765
+ return true ;
766
+ }
767
+ return false ;
768
+ }
769
+
690
770
// Returns the e_type field from an ELF image.
691
771
static uint16_t getELFHeaderType (const unsigned char *ImgData, size_t ImgSize) {
692
772
(void )ImgSize;
693
773
assert (ImgSize >= 18 && " Not enough bytes to have an ELF header type." );
694
774
695
775
bool IsBigEndian = ImgData[5 ] == 2 ;
696
- if (IsBigEndian)
697
- return (static_cast <uint16_t >(ImgData[16 ]) << 8 ) |
698
- static_cast <uint16_t >(ImgData[17 ]);
699
- uint16_t HdrType = 0 ;
700
- std::copy (ImgData + 16 , ImgData + 16 + sizeof (HdrType),
701
- reinterpret_cast <char *>(&HdrType));
702
- return HdrType;
776
+ return readELFValue<uint16_t >(ImgData + 16 , 2 , IsBigEndian);
703
777
}
704
778
705
779
RT::PiDeviceBinaryType getBinaryImageFormat (const unsigned char *ImgData,
@@ -738,6 +812,10 @@ RT::PiDeviceBinaryType getBinaryImageFormat(const unsigned char *ImgData,
738
812
if (HdrType == ELFFmt.Magic )
739
813
return ELFFmt.Fmt ;
740
814
}
815
+ // Newer ZEBIN format does not have a special header type, but can instead
816
+ // be identified by having a required .ze_info section.
817
+ if (checkELFSectionPresent (" .ze_info" , ImgData, ImgSize))
818
+ return PI_DEVICE_BINARY_TYPE_NATIVE;
741
819
}
742
820
}
743
821
return PI_DEVICE_BINARY_TYPE_NONE;
0 commit comments