LCOV - code coverage report
Current view: top level - include - kernel_elf_parser.h (source / functions) Coverage Total Hit
Test: coverage.info_filtered Lines: 79.7 % 256 204
Test Date: 2026-07-27 14:41:20 Functions: 100.0 % 14 14

            Line data    Source code
       1              : /**
       2              :  * Copyright (c) 2026 Huawei Technologies Co., Ltd.
       3              :  * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
       4              :  * CANN Open Software License Agreement Version 2.0 (the "License").
       5              :  * Please refer to the License for details. You may not use this file except in compliance with the License.
       6              :  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
       7              :  * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
       8              :  * See LICENSE in the root of the software repository for the full text of the License.
       9              :  */
      10              : #ifndef KERNEL_ELF_PARSER_H
      11              : #define KERNEL_ELF_PARSER_H
      12              : 
      13              : #include <cstdlib>
      14              : #include <memory>
      15              : #include <stdexcept>
      16              : #include <string>
      17              : #include <unordered_map>
      18              : #include <elf.h>
      19              : #include <cxxabi.h>
      20              : 
      21              : #include "stub_def.h"
      22              : 
      23              : namespace AscendC {
      24              : 
      25              : constexpr uint16_t FUNC_META_TYPE_KERNEL_TYPE = 1U;
      26              : constexpr uint16_t FUNC_META_TYPE_MIX_TASK_RATION = 3U;
      27              : const std::string KERNEL_SECTION_NAME_PREFIX = ".ascend.meta.";
      28              : const std::string KERNEL_MIX_AIV_POSTFIX = "_mix_aiv";
      29              : const std::string KERNEL_MIX_AIC_POSTFIX = "_mix_aic";
      30              : const size_t PREFIX_LEN = KERNEL_SECTION_NAME_PREFIX.length();
      31              : const size_t MIX_SUFFIX_LEN =
      32              :     KERNEL_MIX_AIV_POSTFIX.length(); // KERNEL_MIX_AIC_POSTFIX.length() == KERNEL_MIX_AIV_POSTFIX.length()
      33              : 
      34              : typedef struct {
      35              :     uint16_t type;
      36              :     uint16_t length;
      37              : } ElfTlvHead;
      38              : 
      39              : typedef enum KernelType : unsigned int {
      40              :     K_TYPE_INVALID = 0,
      41              :     K_TYPE_AICORE = 1,
      42              :     K_TYPE_AIC = 2,
      43              :     K_TYPE_AIV = 3,
      44              :     K_TYPE_MIX_AIC_MAIN = 4,
      45              :     K_TYPE_MIX_AIV_MAIN = 5,
      46              :     K_TYPE_AIC_ROLLBACK = 6,
      47              :     K_TYPE_AIV_ROLLBACK = 7,
      48              :     K_TYPE_MAX
      49              : } KernelTypeAsc;
      50              : 
      51              : struct ElfKernelInfo {
      52              :     uint32_t kernelType = 0;
      53              :     uint16_t aicRation = 0;
      54              :     uint16_t aivRation = 0;
      55              : };
      56              : 
      57              : class KernelModeRegister {
      58              : public:
      59           40 :     static KernelModeRegister& GetInstance()
      60              :     {
      61           40 :         static KernelModeRegister instance;
      62           40 :         return instance;
      63              :     }
      64              : 
      65           60 :     static std::string Demangle(const char* symbol)
      66              :     {
      67           60 :         if (symbol == nullptr) {
      68            4 :             throw std::runtime_error("Failed to demangle symbol: null symbol");
      69              :         }
      70              : 
      71           56 :         int status = 0;
      72              :         std::unique_ptr<char, decltype(&std::free)> demangled(
      73           56 :             abi::__cxa_demangle(symbol, nullptr, nullptr, &status), std::free);
      74              :         // abi::__cxa_demangle mallocs memory for the demangled name, so we use unique_ptr to ensure it gets freed
      75              : 
      76           56 :         if (status == 0 && demangled != nullptr) {
      77           88 :             return std::string(demangled.get());
      78              :         }
      79              : 
      80           12 :         if (status == -2) {
      81           24 :             return std::string(symbol);
      82              :         }
      83              : 
      84            0 :         throw std::runtime_error("Failed to demangle symbol: " + std::string(symbol));
      85           56 :     }
      86              : 
      87           24 :     void Register(const std::string& kernelName, KernelMode kernelMode)
      88              :     {
      89           24 :         kernelModeMap[Demangle(kernelName.c_str())] = kernelMode;
      90           24 :     }
      91              : 
      92           24 :     void Clear() { kernelModeMap.clear(); }
      93              : 
      94           24 :     KernelMode GetKenelMode(const char* mangling)
      95              :     {
      96           24 :         std::string kernelName = Demangle(mangling);
      97           24 :         auto it = kernelModeMap.find(kernelName);
      98           24 :         if (it != kernelModeMap.end()) {
      99           40 :             return it->second;
     100              :         }
     101            4 :         throw std::invalid_argument("Kernel mode not found for kernel: " + kernelName);
     102           24 :     }
     103              : 
     104              : private:
     105              :     std::unordered_map<std::string, KernelMode> kernelModeMap;
     106              : };
     107              : 
     108           76 : inline uint64_t ByteGetBigEndian(const uint8_t field[], const int32_t size)
     109              : {
     110           76 :     uint64_t ret = 0UL;
     111              : 
     112           76 :     switch (size) {
     113            4 :         case 1:
     114            4 :             ret = static_cast<uint64_t>(*field);
     115            4 :             break;
     116           36 :         case 2:
     117           36 :             ret = (static_cast<uint64_t>(field[1U])) | ((static_cast<uint64_t>(field[0U])) << 8U); // shift 8 bit
     118           36 :             break;
     119            0 :         case 3:
     120            0 :             ret = (static_cast<uint64_t>(field[2U])) | ((static_cast<uint64_t>(field[1U])) << 8U) |
     121            0 :                   ((static_cast<uint64_t>(field[0U])) << 16U);
     122            0 :             break;
     123           12 :         case 4:
     124           12 :             ret = (static_cast<uint64_t>(field[3U])) | ((static_cast<uint64_t>(field[2U])) << 8U) |
     125           12 :                   ((static_cast<uint64_t>(field[1U])) << 16U) | ((static_cast<uint64_t>(field[0U])) << 24U);
     126           12 :             break;
     127            0 :         case 5:
     128            0 :             ret = (static_cast<uint64_t>(field[4U])) | ((static_cast<uint64_t>(field[3U])) << 8U) |
     129            0 :                   ((static_cast<uint64_t>(field[2U])) << 16U) | ((static_cast<uint64_t>(field[1U])) << 24U) |
     130            0 :                   ((static_cast<uint64_t>(field[0U])) << 32U);
     131            0 :             break;
     132            0 :         case 6:
     133            0 :             ret = (static_cast<uint64_t>(field[5U])) | ((static_cast<uint64_t>(field[4U])) << 8U) |
     134            0 :                   ((static_cast<uint64_t>(field[3U])) << 16U) | ((static_cast<uint64_t>(field[2U])) << 24U) |
     135            0 :                   ((static_cast<uint64_t>(field[1U])) << 32U) | ((static_cast<uint64_t>(field[0U])) << 40U);
     136            0 :             break;
     137            0 :         case 7:
     138            0 :             ret = (static_cast<uint64_t>(field[6U])) | ((static_cast<uint64_t>(field[5U])) << 8U) |
     139            0 :                   ((static_cast<uint64_t>(field[4U])) << 16U) | ((static_cast<uint64_t>(field[3U])) << 24U) |
     140            0 :                   ((static_cast<uint64_t>(field[2U])) << 32U) | ((static_cast<uint64_t>(field[1U])) << 40U) |
     141            0 :                   ((static_cast<uint64_t>(field[0U])) << 48U);
     142            0 :             break;
     143           16 :         case 8:
     144           16 :             ret = (static_cast<uint64_t>(field[7U])) | ((static_cast<uint64_t>(field[6U])) << 8U) |
     145           16 :                   ((static_cast<uint64_t>(field[5U])) << 16U) | ((static_cast<uint64_t>(field[4U])) << 24U) |
     146           16 :                   ((static_cast<uint64_t>(field[3U])) << 32U) | ((static_cast<uint64_t>(field[2U])) << 40U) |
     147           16 :                   ((static_cast<uint64_t>(field[1U])) << 48U) | ((static_cast<uint64_t>(field[0U])) << 56U);
     148           16 :             break;
     149            8 :         default:
     150            8 :             throw std::invalid_argument("Invalid data length: size = " + std::to_string(size) + ", support 1~8 only");
     151              :             break;
     152              :     }
     153              : 
     154           68 :     return ret;
     155              : }
     156              : 
     157          924 : inline uint64_t ByteGetLittleEndian(const uint8_t field[], const int32_t size)
     158              : {
     159          924 :     uint64_t ret = 0UL;
     160              : 
     161          924 :     switch (size) {
     162            4 :         case 1:
     163            4 :             ret = static_cast<uint64_t>(*field);
     164            4 :             break;
     165          300 :         case 2:
     166          300 :             ret = (static_cast<uint64_t>(field[0U])) | ((static_cast<uint64_t>(field[1U])) << 8U); // shift 8 bit
     167          300 :             break;
     168            0 :         case 3:
     169            0 :             ret = (static_cast<uint64_t>(field[0U])) | ((static_cast<uint64_t>(field[1U])) << 8U) |
     170            0 :                   ((static_cast<uint64_t>(field[2U])) << 16U);
     171            0 :             break;
     172          304 :         case 4:
     173          304 :             ret = (static_cast<uint64_t>(field[0U])) | ((static_cast<uint64_t>(field[1U])) << 8U) |
     174          304 :                   ((static_cast<uint64_t>(field[2U])) << 16U) | ((static_cast<uint64_t>(field[3U])) << 24U);
     175          304 :             break;
     176            0 :         case 5:
     177            0 :             ret = (static_cast<uint64_t>(field[0U])) | ((static_cast<uint64_t>(field[1U])) << 8U) |
     178            0 :                   ((static_cast<uint64_t>(field[2U])) << 16U) | ((static_cast<uint64_t>(field[3U])) << 24U) |
     179            0 :                   ((static_cast<uint64_t>(field[4U])) << 32U);
     180            0 :             break;
     181            0 :         case 6: /* Fall through.  */
     182            0 :             ret = (static_cast<uint64_t>(field[0U])) | ((static_cast<uint64_t>(field[1U])) << 8U) |
     183            0 :                   ((static_cast<uint64_t>(field[2U])) << 16U) | ((static_cast<uint64_t>(field[3U])) << 24U) |
     184            0 :                   ((static_cast<uint64_t>(field[4U])) << 32U) | ((static_cast<uint64_t>(field[5U])) << 40U);
     185            0 :             break;
     186            0 :         case 7:
     187            0 :             ret = (static_cast<uint64_t>(field[0U])) | ((static_cast<uint64_t>(field[1U])) << 8U) |
     188            0 :                   ((static_cast<uint64_t>(field[2U])) << 16U) | ((static_cast<uint64_t>(field[3U])) << 24U) |
     189            0 :                   ((static_cast<uint64_t>(field[4U])) << 32U) | ((static_cast<uint64_t>(field[5U])) << 40U) |
     190            0 :                   ((static_cast<uint64_t>(field[6U])) << 48U);
     191            0 :             break;
     192          308 :         case 8:
     193          308 :             ret = (static_cast<uint64_t>(field[0U])) | ((static_cast<uint64_t>(field[1U])) << 8U) |
     194          308 :                   ((static_cast<uint64_t>(field[2U])) << 16U) | ((static_cast<uint64_t>(field[3U])) << 24U) |
     195          308 :                   ((static_cast<uint64_t>(field[4U])) << 32U) | ((static_cast<uint64_t>(field[5U])) << 40U) |
     196          308 :                   ((static_cast<uint64_t>(field[6U])) << 48U) | ((static_cast<uint64_t>(field[7U])) << 56U);
     197          308 :             break;
     198            8 :         default:
     199            8 :             throw std::invalid_argument("Invalid data length: size = " + std::to_string(size) + ", support 1~8 only");
     200              :             break;
     201              :     }
     202              : 
     203          916 :     return ret;
     204              : }
     205              : 
     206              : thread_local static uint64_t (*GetByte)(const uint8_t[], const int32_t) = nullptr;
     207              : 
     208           44 : inline Elf64_Ehdr ParseElfHeader(const uint8_t* const elfData, size_t dataSize)
     209              : {
     210           44 :     if (dataSize < sizeof(Elf64_Ehdr)) {
     211              :         throw std::invalid_argument(
     212           16 :             "Input data size is too small for 64-bit ELF header, get input dataSize: " + std::to_string(dataSize) +
     213           24 :             ", requires at least: " + std::to_string(sizeof(Elf64_Ehdr)));
     214              :     }
     215              : 
     216              :     /* Determine how to read the rest of the header.  */
     217           36 :     switch (elfData[EI_DATA]) {
     218           32 :         case ELFDATANONE:
     219              :         case ELFDATA2LSB:
     220           32 :             GetByte = &ByteGetLittleEndian;
     221           32 :             break;
     222            4 :         case ELFDATA2MSB:
     223            4 :             GetByte = &ByteGetBigEndian;
     224            4 :             break;
     225            0 :         default:
     226            0 :             GetByte = &ByteGetLittleEndian;
     227            0 :             break;
     228              :     }
     229              : 
     230           36 :     const bool is32bitElf = (elfData[EI_CLASS] != ELFCLASS64);
     231              : 
     232              :     /* Read in the rest of the header.  */
     233           36 :     if (is32bitElf) {
     234            4 :         throw std::invalid_argument("Only support input elf is 64-bit format.");
     235              :     }
     236              : 
     237              :     Elf64_Ehdr header;
     238           32 :     size_t offset = EI_NIDENT; // Skip e_ident
     239              : 
     240           32 :     header.e_type = static_cast<uint16_t>(GetByte(elfData + offset, 2));
     241           32 :     offset += 2;
     242           32 :     header.e_machine = static_cast<uint16_t>(GetByte(elfData + offset, 2));
     243           32 :     offset += 2;
     244           32 :     header.e_version = GetByte(elfData + offset, 4);
     245           32 :     offset += 4;
     246           32 :     header.e_entry = GetByte(elfData + offset, 8);
     247           32 :     offset += 8;
     248           32 :     header.e_phoff = GetByte(elfData + offset, 8);
     249           32 :     offset += 8;
     250           32 :     header.e_shoff = GetByte(elfData + offset, 8);
     251           32 :     offset += 8;
     252           32 :     header.e_flags = static_cast<uint32_t>(GetByte(elfData + offset, 4));
     253           32 :     offset += 4;
     254           32 :     header.e_ehsize = static_cast<uint16_t>(GetByte(elfData + offset, 2));
     255           32 :     offset += 2;
     256           32 :     header.e_phentsize = static_cast<uint16_t>(GetByte(elfData + offset, 2));
     257           32 :     offset += 2;
     258           32 :     header.e_phnum = static_cast<uint16_t>(GetByte(elfData + offset, 2));
     259           32 :     offset += 2;
     260           32 :     header.e_shentsize = static_cast<uint16_t>(GetByte(elfData + offset, 2));
     261           32 :     offset += 2;
     262           32 :     header.e_shnum = static_cast<uint16_t>(GetByte(elfData + offset, 2));
     263           32 :     offset += 2;
     264           32 :     header.e_shstrndx = static_cast<uint16_t>(GetByte(elfData + offset, 2));
     265           32 :     return header;
     266              : };
     267              : 
     268           52 : inline Elf64_Shdr GetSectionHeader(const uint8_t* const elfData, size_t dataSize, Elf64_Ehdr header, uint16_t index)
     269              : {
     270           52 :     if (index >= header.e_shnum) {
     271              :         throw std::invalid_argument(
     272            8 :             "Invalid section index, get index: " + std::to_string(index) +
     273           12 :             ", but section number is: " + std::to_string(header.e_shnum));
     274              :     }
     275           48 :     size_t shOffset = header.e_shoff + index * header.e_shentsize;
     276           48 :     if (shOffset + sizeof(Elf64_Shdr) > dataSize) {
     277            4 :         throw std::invalid_argument("Data size is to small for parse section header[" + std::to_string(index) + "]");
     278              :     }
     279           44 :     const uint8_t* data = elfData + shOffset;
     280              :     Elf64_Shdr shdr;
     281              : 
     282           44 :     shdr.sh_name = static_cast<uint32_t>(GetByte(data, 4));
     283           44 :     data += 4;
     284           44 :     shdr.sh_type = static_cast<uint32_t>(GetByte(data, 4));
     285           44 :     data += 4;
     286           44 :     shdr.sh_flags = GetByte(data, 8);
     287           44 :     data += 8;
     288           44 :     shdr.sh_addr = GetByte(data, 8);
     289           44 :     data += 8;
     290           44 :     shdr.sh_offset = GetByte(data, 8);
     291           44 :     data += 8;
     292           44 :     shdr.sh_size = GetByte(data, 4);
     293           44 :     data += 8;
     294           44 :     shdr.sh_link = static_cast<uint32_t>(GetByte(data, 4));
     295           44 :     data += 4;
     296           44 :     shdr.sh_info = static_cast<uint32_t>(GetByte(data, 4));
     297           44 :     data += 4;
     298           44 :     shdr.sh_addralign = GetByte(data, 8);
     299           44 :     data += 8;
     300           44 :     shdr.sh_entsize = GetByte(data, 8);
     301              : 
     302           44 :     return shdr;
     303              : };
     304              : 
     305           32 : inline ElfKernelInfo GetKernelInfo(const uint8_t* const elfData, size_t dataSize, Elf64_Shdr kernelMetaSectionHead)
     306              : {
     307           32 :     uint64_t remainLen = kernelMetaSectionHead.sh_size;
     308           32 :     if (remainLen + kernelMetaSectionHead.sh_offset > dataSize) {
     309            4 :         throw std::invalid_argument("Data size is to small for parse kernel meta section");
     310              :     }
     311           28 :     const uint8_t* curData = elfData + kernelMetaSectionHead.sh_offset;
     312           28 :     ElfKernelInfo kernelInfo;
     313           56 :     while (remainLen > sizeof(ElfTlvHead)) {
     314           32 :         const ElfTlvHead* tlvHead = reinterpret_cast<const ElfTlvHead*>(curData);
     315              :         const uint16_t tlvType =
     316           32 :             static_cast<uint16_t>(GetByte(reinterpret_cast<const uint8_t*>(&(tlvHead->type)), sizeof(uint16_t)));
     317              :         const uint16_t tlvLength =
     318           32 :             static_cast<uint16_t>(GetByte(reinterpret_cast<const uint8_t*>(&(tlvHead->length)), sizeof(uint16_t)));
     319           32 :         if ((sizeof(ElfTlvHead) + tlvLength) > remainLen) {
     320            4 :             throw std::invalid_argument("Invalid TLV length in kernel meta section");
     321              :         }
     322              : 
     323           28 :         if (tlvType == FUNC_META_TYPE_KERNEL_TYPE) {
     324           24 :             if (tlvLength != sizeof(uint32_t)) {
     325            0 :                 throw std::invalid_argument("Invalid kernel type length in kernel meta section");
     326              :             }
     327           24 :             kernelInfo.kernelType = static_cast<uint32_t>(
     328           24 :                 GetByte(reinterpret_cast<const uint8_t*>(curData + sizeof(ElfTlvHead)), sizeof(uint32_t)));
     329            4 :         } else if (tlvType == FUNC_META_TYPE_MIX_TASK_RATION) {
     330            4 :             if (tlvLength != sizeof(uint16_t) * 2) {
     331            0 :                 throw std::invalid_argument("Invalid mix task ration length in kernel meta section");
     332              :             }
     333            4 :             kernelInfo.aicRation = static_cast<uint16_t>(
     334            4 :                 GetByte(reinterpret_cast<const uint8_t*>(curData + sizeof(ElfTlvHead)), sizeof(uint16_t)));
     335            4 :             kernelInfo.aivRation = static_cast<uint16_t>(GetByte(
     336              :                 reinterpret_cast<const uint8_t*>(curData + sizeof(ElfTlvHead) + sizeof(uint16_t)), sizeof(uint16_t)));
     337              :         }
     338           28 :         curData += sizeof(ElfTlvHead) + tlvLength;
     339           28 :         remainLen = remainLen - (sizeof(ElfTlvHead) + tlvLength);
     340              :     }
     341           24 :     return kernelInfo;
     342              : }
     343              : 
     344           48 : inline KernelMode ToKernelMode(ElfKernelInfo kernelInfo)
     345              : {
     346           48 :     if (kernelInfo.kernelType == K_TYPE_INVALID) {
     347            4 :         throw std::invalid_argument("get invalid kernel type");
     348              :     }
     349           44 :     if (kernelInfo.kernelType == K_TYPE_MIX_AIC_MAIN) {
     350           12 :         if (kernelInfo.aicRation == 1 && kernelInfo.aivRation == 0) {
     351            4 :             return KernelMode::AIC_MODE;
     352            8 :         } else if (kernelInfo.aicRation == 1 && kernelInfo.aivRation == 1) {
     353            4 :             return KernelMode::MIX_AIC_1_1;                                  // MIX_AIC_1_1
     354            4 :         } else if (kernelInfo.aicRation == 1 && kernelInfo.aivRation == 2) { // aic num 1, aiv num 2
     355            4 :             return KernelMode::MIX_MODE;                                     // MIX_MODE
     356              :         }
     357           32 :     } else if (kernelInfo.kernelType == K_TYPE_AIC || kernelInfo.kernelType == K_TYPE_AIC_ROLLBACK) {
     358           20 :         return KernelMode::AIC_MODE; // => AIC_MODE
     359           12 :     } else if (
     360           12 :         kernelInfo.kernelType == K_TYPE_AIV || kernelInfo.kernelType == K_TYPE_AIV_ROLLBACK ||
     361            0 :         kernelInfo.kernelType == K_TYPE_MIX_AIV_MAIN) {
     362           12 :         return KernelMode::AIV_MODE; // AIV_MODE
     363              :     }
     364            0 :     return KernelMode::MIX_MODE;
     365              : }
     366              : 
     367              : // Extract kernel name from section name by stripping .ascend.meta. prefix and _mix_aiv/_mix_aic postfix
     368              : // Returns empty string if sectionName is not a kernel meta section
     369           60 : inline std::string ExtractKernelName(const std::string& sectionName)
     370              : {
     371           60 :     if (sectionName.length() > PREFIX_LEN && sectionName.compare(0, PREFIX_LEN, KERNEL_SECTION_NAME_PREFIX) == 0) {
     372           32 :         size_t kernelNameLen = sectionName.length() - PREFIX_LEN;
     373           32 :         if (kernelNameLen > MIX_SUFFIX_LEN) {
     374           28 :             size_t suffixPos = sectionName.length() - MIX_SUFFIX_LEN;
     375           48 :             if (sectionName.compare(suffixPos, MIX_SUFFIX_LEN, KERNEL_MIX_AIV_POSTFIX) == 0 ||
     376           20 :                 sectionName.compare(suffixPos, MIX_SUFFIX_LEN, KERNEL_MIX_AIC_POSTFIX) == 0) {
     377           16 :                 kernelNameLen -= MIX_SUFFIX_LEN;
     378              :             }
     379              :         }
     380           32 :         return sectionName.substr(PREFIX_LEN, kernelNameLen);
     381              :     }
     382           56 :     return "";
     383              : }
     384              : 
     385           12 : inline void ParseKernelSections(
     386              :     const uint8_t* const elfData, size_t dataSize, Elf64_Ehdr header, Elf64_Shdr shStrTabHdr)
     387              : {
     388           12 :     const uint8_t* shStrTab = elfData + shStrTabHdr.sh_offset;
     389           12 :     if (shStrTabHdr.sh_offset + shStrTabHdr.sh_size > dataSize) {
     390            0 :         throw std::invalid_argument("Data size is to small for parse section header string table");
     391              :     }
     392           40 :     for (int i = 0; i < header.e_shnum; ++i) {
     393           28 :         Elf64_Shdr shdr = GetSectionHeader(elfData, dataSize, header, i);
     394           28 :         std::string sectionName(reinterpret_cast<const char*>(shStrTab) + shdr.sh_name);
     395           28 :         std::string kernelName = ExtractKernelName(sectionName);
     396           28 :         if (!kernelName.empty()) {
     397              :             try {
     398           16 :                 ElfKernelInfo kernelInfo = GetKernelInfo(elfData, dataSize, shdr);
     399           16 :                 KernelMode kernelMode = ToKernelMode(kernelInfo);
     400           16 :                 KernelModeRegister::GetInstance().Register(kernelName, kernelMode);
     401            0 :             } catch (std::invalid_argument& e) {
     402            0 :                 throw std::invalid_argument("Failed to get kernel mode from section " + sectionName + ": " + e.what());
     403            0 :             }
     404              :         }
     405           28 :     }
     406           12 : }
     407              : 
     408           16 : inline void RegisterKernelElf(const uint8_t* const elfData, size_t dataSize)
     409              : {
     410           16 :     Elf64_Ehdr header = ParseElfHeader(elfData, dataSize);
     411           12 :     Elf64_Shdr shStrTabHdr = GetSectionHeader(elfData, dataSize, header, header.e_shstrndx);
     412           12 :     ParseKernelSections(elfData, dataSize, header, shStrTabHdr);
     413           12 : }
     414              : 
     415              : } // namespace AscendC
     416              : #endif // KERNEL_ELF_PARSER_H
        

Generated by: LCOV version 2.0-1