LCOV - code coverage report
Current view: top level - adump/exception - dump_ELF.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 93.8 % 146 137
Test Date: 2026-07-28 10:54:24 Functions: 100.0 % 27 27

            Line data    Source code
       1              : /**
       2              :  * Copyright (c) 2025 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              : 
      11              : #include "dump_ELF.h"
      12              : #include "log/adx_log.h"
      13              : #include "mmpa_api.h"
      14              : 
      15              : namespace Adx{
      16              : namespace ELF{
      17              : 
      18              : namespace {
      19              : constexpr Elf64_Half EM_HIIPU = 0x1029;
      20              : constexpr Elf64_Word EV_VERSION = 0x01;
      21              : constexpr Elf64_Off ADD_ALIGN = 16;
      22              : const std::string STRTAB_SECTION_NAME = ".shstrtab";
      23              : }
      24              : 
      25          374 : Section::Section(Elf64_Word type)
      26              : {
      27          374 :     header_.sh_type = type;
      28          374 : }
      29              : 
      30          356 : void Section::SetData(std::string &data)
      31              : {
      32          356 :     data_ = std::move(data);
      33          356 :     header_.sh_size = data_.size();
      34          356 : }
      35              : 
      36           84 : void Section::SetAddr(Elf64_Addr addr)
      37              : {
      38           84 :     header_.sh_addr = addr;
      39           84 : }
      40              : 
      41          769 : void Section::SetOffSet(Elf64_Off offset)
      42              : {
      43          769 :     header_.sh_offset = offset;
      44          769 : }
      45              : 
      46          113 : void Section::SetEntSize(Elf64_Word entSize)
      47              : {
      48          113 :     header_.sh_entsize = entSize;
      49          113 : }
      50              : 
      51          373 : void Section::SetNameIndex(Elf64_Word nameIndex)
      52              : {
      53          373 :     header_.sh_name = nameIndex;
      54          373 : }
      55              : 
      56          208 : void Section::SetLink(Elf64_Word link)
      57              : {
      58          208 :     header_.sh_link = link;
      59          208 : }
      60              : 
      61          208 : void Section::SetInfo(Elf64_Word info)
      62              : {
      63          208 :     header_.sh_info = info;
      64          208 : }
      65              : 
      66          373 : void Section::SetIndex(uint32_t index)
      67              : {
      68          373 :     index_ = index;
      69          373 : }
      70              : 
      71          340 : uint32_t Section::GetIndex() const
      72              : {
      73          340 :     return index_;
      74              : }
      75              : 
      76          769 : void Section::Save(std::ofstream &ofs, std::streampos headerPosition)
      77              : {
      78          769 :     SaveHeader(ofs, headerPosition);
      79          769 :     SaveData(ofs);
      80          769 : }
      81              : 
      82          769 : void Section::SaveHeader(std::ofstream &ofs, std::streampos offset)
      83              : {
      84          769 :     ofs.seekp(offset);
      85          769 :     ofs.write(reinterpret_cast<const char *>(&header_), sizeof(header_));
      86          769 : }
      87              : 
      88          769 : void Section::SaveData(std::ofstream &ofs)
      89              : {
      90          769 :     ofs.seekp(header_.sh_offset);
      91          769 :     ofs.write(data_.c_str(), data_.size());
      92          769 : }
      93              : 
      94          769 : Elf64_Xword Section::GetSize() const
      95              : {
      96          769 :     return header_.sh_size;
      97              : }
      98              : 
      99            2 : void Section::SetAddrAlign(Elf64_Xword addrAlign)
     100              : {
     101            2 :     header_.sh_addralign = addrAlign;
     102            2 : }
     103              : 
     104          771 : Elf64_Xword Section::GetAddrAlign() const
     105              : {
     106          771 :     return header_.sh_addralign;
     107              : }
     108              : 
     109           15 : DumpELF::DumpELF()
     110              : {
     111           15 :     header_.e_ident[EI_MAG0] = ELFMAG0;
     112           15 :     header_.e_ident[EI_MAG1] = ELFMAG1;
     113           15 :     header_.e_ident[EI_MAG2] = ELFMAG2;
     114           15 :     header_.e_ident[EI_MAG3] = ELFMAG3;
     115           15 :     header_.e_ident[EI_CLASS] = ELFCLASS64;
     116           15 :     header_.e_ident[EI_DATA] = ELFDATA2LSB;
     117           15 :     header_.e_ident[EI_VERSION] = EV_CURRENT;
     118           15 :     header_.e_ehsize = sizeof(Elf64_Ehdr);
     119           15 :     header_.e_type = ET_CORE;
     120           15 :     header_.e_machine = EM_HIIPU;
     121           15 :     header_.e_version = EV_VERSION;
     122           15 :     CreateMandatorySection();
     123           15 : }
     124              : 
     125          373 : SectionPtr DumpELF::CreateSection(Elf64_Word type)
     126              : {
     127              :     try {
     128          373 :         sections_.emplace_back(std::make_shared<Section>(type));
     129          373 :         sections_.back()->SetIndex(static_cast<uint32_t>(sections_.size() - 1));
     130          373 :         return sections_.back();
     131            0 :     } catch (std::exception &ex) {
     132            0 :         IDE_LOGE("Section make shared failed, strerr=%s", ex.what());
     133            0 :         return nullptr;
     134            0 :     }
     135              : }
     136              : 
     137           15 : void DumpELF::CreateMandatorySection()
     138              : {
     139              :     // first section is null section
     140           15 :     SectionPtr sec0 = CreateSection(SHT_NULL);
     141           15 :     IDE_CTRL_VALUE_FAILED(sec0 != nullptr, return, "Create first NULL section failed");
     142           15 :     sectionNameStream_ << '\0';
     143           15 :     sec0->SetNameIndex(0);
     144           15 : }
     145              : 
     146          358 : SectionPtr DumpELF::AddSection(Elf64_Word type, const std::string &name)
     147              : {
     148          358 :     SectionPtr newSection = CreateSection(type);
     149          358 :     if (newSection == nullptr) {
     150            0 :         return nullptr;
     151              :     }
     152              : 
     153          358 :     Elf64_Word nameIndex = 0;
     154          358 :     if (sectionNameTable_.find(name) != sectionNameTable_.end()) {
     155          273 :         nameIndex = sectionNameTable_[name];
     156              :     } else {
     157           85 :         nameIndex = sectionNameStream_.tellp();
     158           85 :         sectionNameStream_ << name << '\0';
     159           85 :         sectionNameTable_[name] = nameIndex;
     160              :     }
     161          358 :     newSection->SetNameIndex(nameIndex);
     162              : 
     163          358 :     return newSection;
     164          358 : }
     165              : 
     166          209 : SectionPtr DumpELF::GetSectionByIndex(uint32_t index) const
     167              : {
     168          209 :     IDE_CTRL_VALUE_FAILED(index < sections_.size(), return nullptr, "Get section failed, index %u out of range %u",
     169              :         index, sections_.size());
     170              : 
     171          208 :     return sections_[index];
     172              : }
     173              : 
     174           10 : void DumpELF::Save(const std::string &filename)
     175              : {
     176           10 :     IDE_CTRL_VALUE_FAILED(mmAccess2(filename.c_str(), F_OK) != EN_OK, return,
     177              :         "file %s already exist", filename.c_str());
     178              : 
     179            9 :     int32_t fd = mmOpen2(filename.c_str() ,M_RDWR | M_CREAT, M_IRUSR | M_IWUSR);
     180            9 :     IDE_CTRL_VALUE_FAILED(fd >= 0, return, "open file %s failed, strerr=%s", filename.c_str(), strerror(errno));
     181            9 :     close(fd);
     182              : 
     183            9 :     std::ofstream ofs(filename, std::ios::binary);
     184            9 :     IDE_CTRL_VALUE_FAILED(ofs.is_open(), return, "open file %s failed, strerr=%s", filename.c_str(), strerror(errno));
     185              : 
     186            9 :     SetSectionHeaderStringTable();
     187              : 
     188            9 :     header_.e_shentsize = sizeof(Elf64_Shdr);
     189            9 :     header_.e_shnum = sections_.size();
     190              : 
     191            9 :     currentFilePos_ = sizeof(Elf64_Ehdr);
     192            9 :     LayoutSections();
     193            9 :     LayoutSectionTable();
     194              : 
     195            9 :     if (!SaveHeader(ofs)) {
     196            0 :         IDE_LOGE("Failed to save ELF header");
     197            0 :         ofs.close();
     198            0 :         return;
     199              :     }
     200            9 :     SaveSections(ofs);
     201              : 
     202            9 :     ofs.close();
     203            9 :     IDE_LOGE("Save dump file %s", filename.c_str());
     204              : 
     205            9 :     int32_t err = mmChmod(filename.c_str(), M_IRUSR);  // 落盘文件置为最小权限:用户只读, 400
     206            9 :     IDE_CTRL_VALUE_WARN(err == 0, return, "mmChmod %s failed, strerr=%s", filename.c_str(), strerror(errno));
     207            9 : }
     208              : 
     209            9 : void DumpELF::SetSectionHeaderStringTable()
     210              : {
     211            9 :     SectionPtr section = AddSection(SHT_STRTAB, STRTAB_SECTION_NAME);
     212            9 :     IDE_CTRL_VALUE_WARN(section != nullptr, return, "Create %s section failed.", STRTAB_SECTION_NAME.c_str());
     213            9 :     std::string data = sectionNameStream_.str();
     214            9 :     section->SetData(data);
     215            9 :     header_.e_shstrndx = sections_.size() - 1;
     216            9 : }
     217              : 
     218            9 : void DumpELF::LayoutSections()
     219              : {
     220          778 :     for (const auto &section : sections_) {
     221          769 :         Elf64_Xword sectionAlign = section->GetAddrAlign();
     222          769 :         if ((sectionAlign > 1) && (currentFilePos_ % sectionAlign != 0)) {
     223            0 :             currentFilePos_ += sectionAlign - (currentFilePos_ % sectionAlign);
     224              :         }
     225          769 :         section->SetOffSet(currentFilePos_);
     226          769 :         currentFilePos_ += section->GetSize();
     227              :     }
     228            9 : }
     229              : 
     230            9 : void DumpELF::LayoutSectionTable()
     231              : {
     232            9 :     if (currentFilePos_ % ADD_ALIGN != 0) {
     233            9 :         currentFilePos_ += ADD_ALIGN - (currentFilePos_ % ADD_ALIGN);
     234              :     }
     235            9 :     header_.e_shoff = currentFilePos_;
     236            9 : }
     237              : 
     238            9 : bool DumpELF::SaveHeader(std::ofstream &ofs) const
     239              : {
     240            9 :     ofs.seekp(0);
     241            9 :     ofs.write(reinterpret_cast<const char *>(&header_), sizeof(header_));
     242            9 :     return ofs.good();
     243              : }
     244              : 
     245            9 : void DumpELF::SaveSections(std::ofstream &ofs)
     246              : {
     247          778 :     for (uint32_t i = 0; i < sections_.size(); ++i) {
     248          769 :         std::streampos headerPosition = header_.e_shoff + i * sizeof(Elf64_Shdr);
     249          769 :         sections_[i]->Save(ofs, headerPosition);
     250          769 :         IDE_CTRL_VALUE_FAILED_NODO(ofs.good(), continue, "save section %u failed", i);
     251              :     }
     252            9 : }
     253              : 
     254              : }
     255              : }
        

Generated by: LCOV version 2.0-1