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 §ion : 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 : }
|