Skip to content

Commit

Permalink
[NFCI][SYCL] Refactor getBinaryImageFormat (#12586)
Browse files Browse the repository at this point in the history
A future PR will add support for magic numbers other than four bytes.
Refactor the code to make those future changes easier to review.
  • Loading branch information
aelovikov-intel authored Feb 2, 2024
1 parent d3d6e78 commit 153ccbe
Showing 1 changed file with 32 additions and 38 deletions.
70 changes: 32 additions & 38 deletions sycl/source/detail/pi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -685,45 +685,39 @@ static uint16_t getELFHeaderType(const unsigned char *ImgData, size_t ImgSize) {
sycl::detail::pi::PiDeviceBinaryType
getBinaryImageFormat(const unsigned char *ImgData, size_t ImgSize) {
// Top-level magic numbers for the recognized binary image formats.
struct {
sycl::detail::pi::PiDeviceBinaryType Fmt;
const uint32_t Magic;
} Fmts[] = {{PI_DEVICE_BINARY_TYPE_SPIRV, 0x07230203},
{PI_DEVICE_BINARY_TYPE_LLVMIR_BITCODE, 0xDEC04342},
// 'I', 'N', 'T', 'C' ; Intel native
{PI_DEVICE_BINARY_TYPE_NATIVE, 0x43544E49}};

if (ImgSize >= sizeof(Fmts[0].Magic)) {
std::remove_const_t<decltype(Fmts[0].Magic)> Hdr = 0;
std::copy(ImgData, ImgData + sizeof(Hdr), reinterpret_cast<char *>(&Hdr));

// Check headers for direct formats.
for (const auto &Fmt : Fmts) {
if (Hdr == Fmt.Magic)
return Fmt.Fmt;
}

// ELF e_type for recognized binary image formats.
struct {
sycl::detail::pi::PiDeviceBinaryType Fmt;
const uint16_t Magic;
} ELFFmts[] = {{PI_DEVICE_BINARY_TYPE_NATIVE, 0xFF04}, // OpenCL executable
{PI_DEVICE_BINARY_TYPE_NATIVE, 0xFF12}}; // ZEBIN executable

// ELF files need to be parsed separately. The header type ends after 18
// bytes.
if (Hdr == 0x464c457F && ImgSize >= 18) {
uint16_t HdrType = getELFHeaderType(ImgData, ImgSize);
for (const auto &ELFFmt : ELFFmts) {
if (HdrType == ELFFmt.Magic)
return ELFFmt.Fmt;
}
// Newer ZEBIN format does not have a special header type, but can instead
// be identified by having a required .ze_info section.
if (checkELFSectionPresent(".ze_info", ImgData, ImgSize))
return PI_DEVICE_BINARY_TYPE_NATIVE;
}
auto MatchMagicNumber = [&](auto Number) {
return ImgSize >= sizeof(Number) &&
std::memcmp(ImgData, &Number, sizeof(Number)) == 0;
};

if (MatchMagicNumber(uint32_t{0x07230203}))
return PI_DEVICE_BINARY_TYPE_SPIRV;

if (MatchMagicNumber(uint32_t{0xDEC04342}))
return PI_DEVICE_BINARY_TYPE_LLVMIR_BITCODE;

if (MatchMagicNumber(uint32_t{0x43544E49}))
// 'I', 'N', 'T', 'C' ; Intel native
return PI_DEVICE_BINARY_TYPE_LLVMIR_BITCODE;

// Check for ELF format, size requirements include data we'll read in case of
// succesful match.
if (ImgSize >= 18 && MatchMagicNumber(uint32_t{0x464c457F})) {
uint16_t ELFHdrType = getELFHeaderType(ImgData, ImgSize);
if (ELFHdrType == 0xFF04)
// OpenCL executable.
return PI_DEVICE_BINARY_TYPE_NATIVE;

if (ELFHdrType == 0xFF12)
// ZEBIN executable.
return PI_DEVICE_BINARY_TYPE_NATIVE;

// Newer ZEBIN format does not have a special header type, but can instead
// be identified by having a required .ze_info section.
if (checkELFSectionPresent(".ze_info", ImgData, ImgSize))
return PI_DEVICE_BINARY_TYPE_NATIVE;
}

return PI_DEVICE_BINARY_TYPE_NONE;
}

Expand Down

0 comments on commit 153ccbe

Please sign in to comment.