1 /*
2 * Copyright (c) Huawei Technologies Co., Ltd. 2022. All rights reserved.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include <elf_file.h>
16
17 #include <cinttypes>
18
19 namespace OHOS {
20 namespace Developtools {
21 namespace Hiebpf {
22
23 constexpr uint32_t MAX_SIZE = INT_MAX;
24
ElfFile(const std::string & filename)25 ElfFile::ElfFile(const std::string &filename)
26 {
27 fd_ = open(filename.c_str(), O_RDONLY);
28 if (fd_ != -1) {
29 struct stat sb;
30 if (fstat(fd_, &sb) == -1) {
31 HHLOGE(true, "unable to check the file size");
32 } else {
33 HHLOGD(true, "file stat size %" PRIu64 " ", sb.st_size);
34 mmap_ = mmap(0, sb.st_size, PROT_READ, MAP_PRIVATE, fd_, 0);
35 if (mmap_ == MMAP_FAILED) {
36 HHLOGE(true, "unable to map the file size %" PRIu64 " ", sb.st_size);
37 mmapSize_ = 0;
38 } else {
39 mmapSize_ = sb.st_size;
40 HHLOGD(true, "mmap build with size %" PRIu64 " ", mmapSize_);
41 }
42 }
43 }
44 }
45
~ElfFile()46 ElfFile::~ElfFile()
47 {
48 if (mmap_ != MMAP_FAILED) {
49 munmap(mmap_, mmapSize_);
50 }
51
52 if (fd_ != -1) {
53 close(fd_);
54 fd_ = -1;
55 }
56 }
57
MakeUnique(const std::string & filename)58 std::unique_ptr<ElfFile> ElfFile::MakeUnique(const std::string &filename)
59 {
60 std::unique_ptr<ElfFile> file {new (std::nothrow) ElfFile(filename)};
61 CHECK_NOTNULL(file, nullptr, "Error in ElfFile::MakeUnique(): ElfFile::ElfFile() failed");
62 CHECK_TRUE(file->IsOpened(), nullptr, "Error in ElfFile::MakeUnique(): elf file not opended");
63 CHECK_TRUE(file->ParseFile(), nullptr, "parse elf file failed");
64 return file;
65 }
66
ParseFile()67 bool ElfFile::ParseFile()
68 {
69 CHECK_TRUE(ParseElfHeader(), false, "Error in ElfFile::MakeUnique(): ElfFile::ParseElfHeader() failed");
70 CHECK_TRUE(ParsePrgHeaders(), false, "Error in ElfFile::MakeUnique(): ElfFile::ParsePrgHeaders() failed");
71 CHECK_TRUE(ParseSecNamesStr(), false, "Error in ElfFile::MakeUnique(): ElfFile::ParseSecNamesStr() failed");
72 CHECK_TRUE(ParseSecHeaders(), false, "Error in ElfFile::MakeUnique(): ElfFile::ParseSecHeaders() failed");
73 return true;
74 }
75
ParseElfHeader()76 bool ElfFile::ParseElfHeader()
77 {
78 ssize_t ret = lseek(fd_, 0, SEEK_SET);
79 CHECK_TRUE(ret == 0, false, "lseek ret %zu", ret);
80
81 unsigned char ehdrBuf[ehdr64Size] {0};
82 size_t readsize = ReadFile(ehdrBuf, ehdr64Size);
83 CHECK_TRUE(readsize >= ehdr64Size, false,
84 "file size not enough, try read %zu, only have %zu", ehdr64Size, readsize);
85 ehdr_ = ElfHeader::MakeUnique(ehdrBuf, readsize);
86 return !(ehdr_ == nullptr);
87 }
88
ParsePrgHeaders()89 bool ElfFile::ParsePrgHeaders()
90 {
91 size_t phdrSize = ehdr_->phdrEntSize_;
92 size_t numPhdrs = ehdr_->phdrNumEnts_;
93 uint64_t phdrOffset = ehdr_->phdrOffset_;
94 int64_t ret = lseek(fd_, phdrOffset, SEEK_SET);
95 if (ret != static_cast<int64_t>(phdrOffset)) {
96 return false;
97 }
98 if (phdrSize * numPhdrs > MAX_SIZE) {
99 HHLOGE(true, "ParsePrgHeaders size exceeds max size");
100 return false;
101 }
102 char *phdrsBuf = new (std::nothrow) char[phdrSize * numPhdrs];
103 CHECK_NOTNULL(phdrsBuf, false, "Error in ELF::ElfFile::ParsePrgHeaders(): new failed");
104
105 ret = ReadFile(phdrsBuf, phdrSize * numPhdrs);
106 if (ret != static_cast<int64_t>(phdrSize * numPhdrs)) {
107 delete[] phdrsBuf;
108 phdrsBuf = nullptr;
109 return false;
110 }
111 char *phdrBuf = phdrsBuf;
112 for (size_t count = 0; count < numPhdrs; ++count) {
113 std::unique_ptr<ProgramHeader> phdr = ProgramHeader::MakeUnique(phdrBuf, phdrSize);
114 if (phdr == nullptr) {
115 delete[] phdrsBuf;
116 phdrsBuf = nullptr;
117 HHLOGE(true, "Error in Elf::ParsePrgHeaders(): ProgramHeader::MakeUnique() failed");
118 return false;
119 }
120 phdrs_.push_back(std::move(phdr));
121 phdrBuf += phdrSize;
122 }
123 delete[] phdrsBuf;
124 phdrsBuf = nullptr;
125 return true;
126 }
127
ParseSecNamesStr()128 bool ElfFile::ParseSecNamesStr()
129 {
130 // get string table section header
131 size_t shdrSize = ehdr_->shdrEntSize_;
132 size_t shdrIndex = ehdr_->shdrStrTabIdx_;
133 uint64_t shdrOffset = ehdr_->shdrOffset_ + ((uint64_t)shdrIndex) * shdrSize;
134 int64_t ret = lseek(fd_, shdrOffset, SEEK_SET);
135 if (ret != static_cast<int64_t>(shdrOffset)) {
136 return false;
137 }
138 if (shdrSize > MAX_SIZE) {
139 HHLOGE(true, "ParseSecNamesStr size exceeds max size");
140 return false;
141 }
142 char *shdrBuf = new (std::nothrow) char[shdrSize];
143 CHECK_NOTNULL(shdrBuf, false, "Error in ElfFile::ParseSecNamesStr(): new failed");
144
145 ret = ReadFile(shdrBuf, shdrSize);
146 if (ret != static_cast<int64_t>(shdrSize)) {
147 delete[] shdrBuf;
148 shdrBuf = nullptr;
149 return false;
150 }
151 const std::string secName {".shstrtab"};
152 shdrs_[secName] = SectionHeader::MakeUnique(shdrBuf, shdrSize, shdrIndex);
153 if (shdrs_[secName] == nullptr) {
154 HHLOGE(true, "Error in ElfFile::ParseSecNamesStr(): SectionHeader::MakeUnique() failed");
155 delete[] shdrBuf;
156 shdrBuf = nullptr;
157 return false;
158 }
159 delete[] shdrBuf;
160 shdrBuf = nullptr;
161
162 // get content of string section table
163 uint64_t secOffset = shdrs_[secName]->fileOffset_;
164 size_t secSize = shdrs_[secName]->secSize_;
165 ret = lseek(fd_, secOffset, SEEK_SET);
166 if (ret != static_cast<int64_t>(secOffset)) {
167 return false;
168 }
169 if (secSize > MAX_SIZE) {
170 HHLOGE(true, "ParseSecNamesStr size exceeds max size");
171 return false;
172 }
173 char *secNamesBuf = new (std::nothrow) char[secSize];
174 CHECK_NOTNULL(secNamesBuf, false, "Error in ElfFile::ParseSecNamesStr(): new secNamesBuf failed");
175 ret = ReadFile(secNamesBuf, secSize);
176 if (ret != static_cast<int64_t>(secSize)) {
177 delete[] secNamesBuf;
178 secNamesBuf = nullptr;
179 return false;
180 }
181 secNamesStr_ = std::string(secNamesBuf, secNamesBuf + secSize);
182 delete[] secNamesBuf;
183 secNamesBuf = nullptr;
184 return true;
185 }
186
ParseSecHeaders()187 bool ElfFile::ParseSecHeaders()
188 {
189 size_t shdrSize = ehdr_->shdrEntSize_;
190 size_t numShdrs = ehdr_->shdrNumEnts_;
191 uint64_t shdrOffset = ehdr_->shdrOffset_;
192 int64_t ret = lseek(fd_, shdrOffset, SEEK_SET);
193 if (ret != static_cast<int64_t>(shdrOffset)) {
194 return false;
195 }
196 if (shdrSize * numShdrs > MAX_SIZE) {
197 HHLOGE(true, "ParseSecHeaders size exceeds max size");
198 return false;
199 }
200 char *shdrsBuf = new (std::nothrow) char[shdrSize * numShdrs];
201 CHECK_NOTNULL(shdrsBuf, false, "Error in ELF::ElfFile::ParseSecHeaders(): new failed");
202
203 ret = ReadFile(shdrsBuf, shdrSize * numShdrs);
204 if (ret != static_cast<int64_t>(shdrSize * numShdrs)) {
205 delete[] shdrsBuf;
206 shdrsBuf = nullptr;
207 return false;
208 }
209
210 char *shdrBuf = shdrsBuf;
211 for (size_t count = 0; count < numShdrs; ++count) {
212 if (count == ehdr_->shdrStrTabIdx_) {
213 shdrBuf += shdrSize;
214 continue;
215 }
216 std::unique_ptr<SectionHeader> shdr = SectionHeader::MakeUnique(shdrBuf, shdrSize, count);
217 if (shdr == nullptr) {
218 delete[] shdrsBuf;
219 shdrsBuf = nullptr;
220 return false;
221 }
222 std::string secName = GetSectionName(shdr->nameIndex_);
223 shdrs_[secName] = std::move(shdr);
224 shdr.reset(nullptr);
225 shdrBuf += shdrSize;
226 }
227 delete[] shdrsBuf;
228 shdrsBuf = nullptr;
229 return true;
230 }
231
GetSectionName(const uint32_t startIndex)232 std::string ElfFile::GetSectionName(const uint32_t startIndex)
233 {
234 if (startIndex >= secNamesStr_.size()) {
235 HHLOGF(true, "out_of_range %s ,endIndex %d ", secNamesStr_.c_str(), startIndex);
236 return "";
237 }
238 size_t endIndex {startIndex};
239 for (; endIndex < secNamesStr_.size(); ++endIndex) {
240 if (secNamesStr_[endIndex] == '\0') {
241 break;
242 }
243 }
244 return secNamesStr_.substr(startIndex, endIndex - startIndex);
245 }
246
247 // ElfHeader
MakeUnique(unsigned char * const ehdrBuf,const std::size_t bufSize)248 std::unique_ptr<ElfHeader> ElfHeader::MakeUnique(unsigned char * const ehdrBuf,
249 const std::size_t bufSize)
250 {
251 std::unique_ptr<ElfHeader> ehdr {new (std::nothrow) ElfHeader()};
252 CHECK_NOTNULL(ehdr, nullptr, "ElfHeader() failed");
253 CHECK_TRUE(ehdr->Init(ehdrBuf, bufSize), nullptr, "ElfHeader::Init(ehdrBuf, bufSize) failed\n");
254 return ehdr;
255 }
256
Init(unsigned char * const ehdrBuf,const std::size_t bufSize)257 bool ElfHeader::Init(unsigned char * const ehdrBuf, const std::size_t bufSize)
258 {
259 std::string magicStr {ehdrBuf, ehdrBuf + SELFMAG};
260 std::string elfMagic {ELFMAG};
261 CHECK_TRUE(magicStr.compare(elfMagic) == 0, false, "elf magic not found");
262 std::copy(ehdrBuf, ehdrBuf + EI_NIDENT, ehdrIdent_);
263
264 if (ehdrBuf[EI_CLASS] == ELFCLASS32 && ParseElf32Header(ehdrBuf, bufSize)) {
265 return true;
266 }
267 if (ehdrBuf[EI_CLASS] == ELFCLASS64 && ParseElf64Header(ehdrBuf, bufSize)) {
268 return true;
269 }
270 HHLOGE(true, "init elf header failed, elf header buffer dumped");
271 return false;
272 }
273
ParseElf32Header(unsigned char * const ehdrBuf,const std::size_t bufSize)274 bool ElfHeader::ParseElf32Header(unsigned char * const ehdrBuf, const std::size_t bufSize)
275 {
276 if (bufSize < ehdr32Size) {
277 HHLOGE(true, "bad elf32 header buffer");
278 return false;
279 }
280 size_t curIndex {EI_NIDENT};
281 uint16_t *u2Buf = reinterpret_cast<uint16_t *>(ehdrBuf + curIndex);
282 type_ = u2Buf[0];
283 curIndex += sizeof(uint16_t);
284
285 u2Buf = reinterpret_cast<uint16_t *>(ehdrBuf + curIndex);
286 machine_ = u2Buf[0];
287 curIndex += sizeof(uint16_t);
288
289 uint32_t *u4Buf = reinterpret_cast<uint32_t *>(ehdrBuf + curIndex);
290 elfVersion_ = u4Buf[0];
291 curIndex += sizeof(uint32_t);
292
293 u4Buf = reinterpret_cast<uint32_t *>(ehdrBuf + curIndex);
294 prgEntryVaddr_ = u4Buf[0];
295 curIndex += sizeof(uint32_t);
296
297 u4Buf = reinterpret_cast<uint32_t *>(ehdrBuf + curIndex);
298 phdrOffset_ = u4Buf[0];
299 curIndex += sizeof(uint32_t);
300
301 u4Buf = reinterpret_cast<uint32_t *>(ehdrBuf + curIndex);
302 shdrOffset_ = u4Buf[0];
303 curIndex += sizeof(uint32_t);
304
305 u4Buf = reinterpret_cast<uint32_t *>(ehdrBuf + curIndex);
306 ehdrFlags_ = u4Buf[0];
307 curIndex += sizeof(uint32_t);
308
309 u2Buf = reinterpret_cast<uint16_t *>(ehdrBuf + curIndex);
310 ehdrSize_ = u2Buf[0];
311 curIndex += sizeof(uint16_t);
312
313 u2Buf = reinterpret_cast<uint16_t *>(ehdrBuf + curIndex);
314 phdrEntSize_ = u2Buf[0];
315 curIndex += sizeof(uint16_t);
316
317 u2Buf = reinterpret_cast<uint16_t *>(ehdrBuf + curIndex);
318 phdrNumEnts_ = u2Buf[0];
319 curIndex += sizeof(uint16_t);
320
321 u2Buf = reinterpret_cast<uint16_t *>(ehdrBuf + curIndex);
322 shdrEntSize_ = u2Buf[0];
323 curIndex += sizeof(uint16_t);
324
325 u2Buf = reinterpret_cast<uint16_t *>(ehdrBuf + curIndex);
326 shdrNumEnts_ = u2Buf[0];
327 curIndex += sizeof(uint16_t);
328
329 u2Buf = reinterpret_cast<uint16_t *>(ehdrBuf + curIndex);
330 shdrStrTabIdx_ = u2Buf[0];
331
332 return true;
333 }
334
ParseElf64Header(unsigned char * const ehdrBuf,const std::size_t bufSize)335 bool ElfHeader::ParseElf64Header(unsigned char * const ehdrBuf, const std::size_t bufSize)
336 {
337 CHECK_TRUE(bufSize >= ehdr64Size, false, "bad elf64 header buffer");
338 size_t curIndex {EI_NIDENT};
339 uint16_t *u2Buf = reinterpret_cast<uint16_t *>(ehdrBuf + curIndex);
340 type_ = u2Buf[0];
341 curIndex += sizeof(uint16_t);
342
343 u2Buf = reinterpret_cast<uint16_t *>(ehdrBuf + curIndex);
344 machine_ = u2Buf[0];
345 curIndex += sizeof(uint16_t);
346
347 uint32_t *u4Buf = reinterpret_cast<uint32_t *>(ehdrBuf + curIndex);
348 elfVersion_ = u4Buf[0];
349 curIndex += sizeof(uint32_t);
350
351 uint64_t *u8Buf = reinterpret_cast<uint64_t *>(ehdrBuf + curIndex);
352 prgEntryVaddr_ = u8Buf[0];
353 curIndex += sizeof(uint64_t);
354
355 u8Buf = reinterpret_cast<uint64_t *>(ehdrBuf + curIndex);
356 phdrOffset_ = u8Buf[0];
357 curIndex += sizeof(uint64_t);
358
359 u8Buf = reinterpret_cast<uint64_t *>(ehdrBuf + curIndex);
360 shdrOffset_ = u8Buf[0];
361 curIndex += sizeof(uint64_t);
362
363 u4Buf = reinterpret_cast<uint32_t *>(ehdrBuf + curIndex);
364 ehdrFlags_ = u4Buf[0];
365 curIndex += sizeof(uint32_t);
366
367 u2Buf = reinterpret_cast<uint16_t *>(ehdrBuf + curIndex);
368 ehdrSize_ = u2Buf[0];
369 curIndex += sizeof(uint16_t);
370
371 u2Buf = reinterpret_cast<uint16_t *>(ehdrBuf + curIndex);
372 phdrEntSize_ = u2Buf[0];
373 curIndex += sizeof(uint16_t);
374
375 u2Buf = reinterpret_cast<uint16_t *>(ehdrBuf + curIndex);
376 phdrNumEnts_ = u2Buf[0];
377 curIndex += sizeof(uint16_t);
378
379 u2Buf = reinterpret_cast<uint16_t *>(ehdrBuf + curIndex);
380 shdrEntSize_ = u2Buf[0];
381 curIndex += sizeof(uint16_t);
382
383 u2Buf = reinterpret_cast<uint16_t *>(ehdrBuf + curIndex);
384 shdrNumEnts_ = static_cast<long long>(*u2Buf);
385 curIndex += sizeof(uint16_t);
386
387 u2Buf = reinterpret_cast<uint16_t *>(ehdrBuf + curIndex);
388 shdrStrTabIdx_ = u2Buf[0];
389
390 return true;
391 }
392
393 // SectionHeader
394 enum class NUMBER : int {
395 ZERO = 0,
396 ONE = 1,
397 TWO = 2,
398 THREE = 3,
399 FOUR = 4,
400 FIVE = 5,
401 SIX = 6,
402 SEVEN = 7,
403 EIGHT = 8,
404 NINE = 9,
405 TEN = 10,
406 ELEVEN = 11,
407 TWELVE = 12,
408 };
409
MakeUnique(char * const shdrBuf,const size_t bufSize,const size_t index)410 std::unique_ptr<SectionHeader> SectionHeader::MakeUnique(char * const shdrBuf, const size_t bufSize,
411 const size_t index)
412 {
413 std::unique_ptr<SectionHeader> shdr {new (std::nothrow) SectionHeader()};
414 if (shdr == nullptr) {
415 return nullptr;
416 }
417 CHECK_TRUE(shdr->Init(shdrBuf, bufSize, index), nullptr, "SectionHeader::Init(shdrBuf, bufSize, index) failed");
418 return shdr;
419 }
420
ParseSecHeader32(char * const shdrBuf)421 bool SectionHeader::ParseSecHeader32(char * const shdrBuf)
422 {
423 uint32_t *u4Buf = reinterpret_cast<uint32_t *>(shdrBuf);
424 int index {0};
425 nameIndex_ = u4Buf[index];
426 index = static_cast<int>(NUMBER::ONE);
427 secType_ = u4Buf[index];
428 index = static_cast<int>(NUMBER::TWO);
429 secFlags_ = u4Buf[index];
430 index = static_cast<int>(NUMBER::SIX);
431 link_ = u4Buf[index];
432 index = static_cast<int>(NUMBER::SEVEN);
433 info_ = u4Buf[index];
434 index = static_cast<int>(NUMBER::THREE);
435 secVaddr_ = u4Buf[index];
436 index = static_cast<int>(NUMBER::FOUR);
437 fileOffset_ = u4Buf[index];
438 index = static_cast<int>(NUMBER::FIVE);
439 secSize_ = u4Buf[index];
440 index = static_cast<int>(NUMBER::EIGHT);
441 secAddrAlign_ = u4Buf[index];
442 index = static_cast<int>(NUMBER::NINE);
443 secEntrySize_ = u4Buf[index];
444 return true;
445 }
446
ParseSecHeader64(char * const shdrBuf)447 bool SectionHeader::ParseSecHeader64(char * const shdrBuf)
448 {
449 uint64_t *u8Buf = reinterpret_cast<uint64_t *>(shdrBuf);
450 uint32_t *u4Buf = reinterpret_cast<uint32_t *>(shdrBuf);
451 size_t index {0};
452 nameIndex_ = u4Buf[index];
453 index = static_cast<size_t>(NUMBER::ONE);
454 secType_ = u4Buf[index];
455 secFlags_ = u8Buf[index];
456 index = static_cast<size_t>(NUMBER::TEN);
457 link_ = u4Buf[index];
458 index = static_cast<size_t>(NUMBER::ELEVEN);
459 info_ = u4Buf[index];
460 index = static_cast<size_t>(NUMBER::TWO);
461 secVaddr_ = u8Buf[index];
462 index = static_cast<size_t>(NUMBER::THREE);
463 fileOffset_ = u8Buf[index];
464 index = static_cast<size_t>(NUMBER::FOUR);
465 secSize_ = u8Buf[index];
466 index = static_cast<size_t>(NUMBER::SIX);
467 secAddrAlign_ = u8Buf[index];
468 index = static_cast<size_t>(NUMBER::SEVEN);
469 secEntrySize_ = u8Buf[index];
470 return true;
471 }
472
473 // ProgramHeader
MakeUnique(char * const phdrBuf,const size_t bufSize)474 std::unique_ptr<ProgramHeader> ProgramHeader::MakeUnique(char * const phdrBuf, const size_t bufSize)
475 {
476 std::unique_ptr<ProgramHeader> phdr {new (std::nothrow) ProgramHeader()};
477 CHECK_NOTNULL(phdr, nullptr, "ProgramHeader() failed");
478 CHECK_TRUE(phdr->Init(phdrBuf, bufSize), nullptr, "ProgramHeader::Init(phdrBuf, bufSize) failed");
479 return phdr;
480 }
481
ParsePrgHeader32(char * const phdrBuf)482 bool ProgramHeader::ParsePrgHeader32(char * const phdrBuf)
483 {
484 uint32_t *u4Buf = reinterpret_cast<uint32_t *>(phdrBuf);
485 size_t index {0};
486 type_ = u4Buf[index];
487 ++index;
488 offset_ = u4Buf[index];
489 ++index;
490 vaddr_ = u4Buf[index];
491 ++index;
492 paddr_ = u4Buf[index];
493 ++index;
494 fileSize_ = u4Buf[index];
495 ++index;
496 memSize_ = u4Buf[index];
497 ++index;
498 flags_ = u4Buf[index];
499 ++index;
500 secAlign_ = u4Buf[index];
501 return true;
502 }
503
ParsePrgHeader64(char * const phdrBuf)504 bool ProgramHeader::ParsePrgHeader64(char * const phdrBuf)
505 {
506 uint32_t *u4Buf = reinterpret_cast<uint32_t *>(phdrBuf);
507 size_t index {0};
508 type_ = u4Buf[index];
509 ++index;
510 flags_ = u4Buf[index];
511
512 uint64_t *u8Buf = reinterpret_cast<uint64_t *>(phdrBuf);
513 offset_ = u8Buf[index];
514 ++index;
515 vaddr_ = u8Buf[index];
516 ++index;
517 paddr_ = u8Buf[index];
518 ++index;
519 fileSize_ = u8Buf[index];
520 ++index;
521 memSize_ = u8Buf[index];
522 ++index;
523 secAlign_ = u8Buf[index];
524 return true;
525 }
526 } // namespace Hiebpf
527 } // namespace Developtools
528 } // namespace OHOS
529