@@ -687,19 +687,93 @@ DeviceBinaryImage::getProperty(const char *PropName) const {
687687 return *It;
688688}
689689
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+
690770// Returns the e_type field from an ELF image.
691771static uint16_t getELFHeaderType (const unsigned char *ImgData, size_t ImgSize) {
692772 (void )ImgSize;
693773 assert (ImgSize >= 18 && " Not enough bytes to have an ELF header type." );
694774
695775 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);
703777}
704778
705779RT::PiDeviceBinaryType getBinaryImageFormat (const unsigned char *ImgData,
@@ -738,6 +812,10 @@ RT::PiDeviceBinaryType getBinaryImageFormat(const unsigned char *ImgData,
738812 if (HdrType == ELFFmt.Magic )
739813 return ELFFmt.Fmt ;
740814 }
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;
741819 }
742820 }
743821 return PI_DEVICE_BINARY_TYPE_NONE;
0 commit comments