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

Generated by: LCOV version 2.0-1