• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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