• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
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 
16 /* This files contains process dump elf module. */
17 
18 #include "dfx_elf.h"
19 
20 #include <cstdlib>
21 #include <fcntl.h>
22 #include <new>
23 #include <string>
24 #include <sys/mman.h>
25 #include <sys/stat.h>
26 #include <sys/types.h>
27 #include <unistd.h>
28 #include <vector>
29 #include "bits/fcntl.h"
30 #include "dfx_log.h"
31 #include "elf.h"
32 #include "link.h"
33 
34 #ifndef PAGE_SIZE
35 #define PAGE_SIZE 4096
36 #endif
37 
38 namespace OHOS {
39 namespace HiviewDFX {
40 static const int MAX_MAP_SIZE = 65536;
41 
Create(const std::string path)42 std::shared_ptr<DfxElf> DfxElf::Create(const std::string path)
43 {
44     char realPaths[PATH_MAX] = {0};
45     if (!realpath(path.c_str(), realPaths)) {
46         DfxLogWarn("Fail to do realpath(%s).", path.c_str());
47         return nullptr;
48     }
49 
50     auto dfxElf = std::make_shared<DfxElf>();
51 
52     dfxElf->SetFd(open(realPaths, O_RDONLY | O_CLOEXEC));
53 
54     if (dfxElf->fd_ < 0) {
55         DfxLogWarn("Fail to open elf file(%s).", realPaths);
56         return nullptr;
57     }
58 
59     struct stat elfStat;
60     if (fstat(dfxElf->fd_, &elfStat) != 0) {
61         DfxLogWarn("Fail to get elf size.");
62         close(dfxElf->fd_);
63         dfxElf->SetFd(-1);
64         return nullptr;
65     }
66 
67     dfxElf->SetSize((uint64_t)elfStat.st_size);
68     if (!dfxElf->ParseElfHeader()) {
69         DfxLogWarn("Fail to parse elf header.");
70         close(dfxElf->fd_);
71         dfxElf->SetFd(-1);
72         return nullptr;
73     }
74 
75     if (!dfxElf->ParseElfProgramHeader()) {
76         DfxLogWarn("Fail to parse elf program header.");
77         close(dfxElf->GetFd());
78         dfxElf->SetFd(-1);
79         return nullptr;
80     }
81 
82     close(dfxElf->GetFd());
83     dfxElf->SetFd(-1);
84     return dfxElf;
85 }
86 
ParseElfHeader()87 bool DfxElf::ParseElfHeader()
88 {
89     ssize_t nread = read(fd_, &(header_), sizeof(header_));
90     if (nread < 0 || nread != static_cast<long>(sizeof(header_))) {
91         DfxLogWarn("Failed to read elf header.");
92         return false;
93     }
94     return true;
95 }
96 
ParseElfProgramHeader()97 bool DfxElf::ParseElfProgramHeader()
98 {
99     size_t size = header_.e_phnum * sizeof(ElfW(Phdr));
100     if (size > MAX_MAP_SIZE) {
101         DfxLogWarn("Exceed max mmap size.");
102         return false;
103     }
104 
105     size_t offset = header_.e_phoff;
106     size_t startOffset = offset & static_cast<size_t>(getpagesize() - 1);
107     size_t alignedOffset = offset & (~(static_cast<size_t>(getpagesize() - 1)));
108     uint64_t endOffset;
109     if (__builtin_add_overflow(static_cast<uint64_t>(size), static_cast<uint64_t>(offset), &endOffset) ||
110         __builtin_add_overflow(static_cast<uint64_t>(endOffset), static_cast<uint64_t>(startOffset), &endOffset)) {
111         DfxLogWarn("Offset calculate error.");
112         return false;
113     }
114 
115     size_t mapSize = static_cast<size_t>(endOffset - offset);
116     if (mapSize > MAX_MAP_SIZE) {
117         DfxLogWarn("Exceed max mmap size.");
118         return false;
119     }
120 
121     void *map = mmap(nullptr, mapSize, PROT_READ, MAP_PRIVATE, fd_, static_cast<off_t>(alignedOffset));
122     if (map == static_cast<void *>MAP_FAILED) {
123         DfxLogWarn("Failed to mmap elf.");
124         return false;
125     }
126 
127     ElfW(Phdr) *phdrTable = (ElfW(Phdr) *)(static_cast<uint8_t*>(map) + startOffset);
128     for (size_t i = 0; i < header_.e_phnum; i++) {
129         ElfW(Phdr) * phdr = &(phdrTable[i]);
130         if (phdr->p_type != PT_LOAD) {
131             continue;
132         }
133         CreateLoadInfo(phdr->p_vaddr, phdr->p_offset);
134     }
135     munmap(map, mapSize);
136     return true;
137 }
138 
FindRealLoadOffset(uint64_t offset) const139 uint64_t DfxElf::FindRealLoadOffset(uint64_t offset) const
140 {
141     for (auto iter = infos_.begin(); iter != infos_.end(); iter++) {
142         if ((iter->offset & -PAGE_SIZE) == offset) {
143             return offset + (iter->vaddr - iter->offset);
144         }
145     }
146     return offset;
147 }
148 
CreateLoadInfo(uint64_t vaddr,uint64_t offset)149 void DfxElf::CreateLoadInfo(uint64_t vaddr, uint64_t offset)
150 {
151     std::unique_ptr<ElfLoadInfo> info(new ElfLoadInfo());
152     if (info == nullptr) {
153         return;
154     }
155     info->vaddr = vaddr;
156     info->offset = offset;
157 
158     infos_.push_back(*info);
159 }
160 
GetName() const161 std::string DfxElf::GetName() const
162 {
163     return name_;
164 }
165 
SetName(const std::string & name)166 void DfxElf::SetName(const std::string &name)
167 {
168     name_ = name;
169 }
170 
GetPath() const171 std::string DfxElf::GetPath() const
172 {
173     return path_;
174 }
175 
SetPath(const std::string & path)176 void DfxElf::SetPath(const std::string &path)
177 {
178     path_ = path;
179 }
180 
ElfW(Ehdr)181 ElfW(Ehdr) DfxElf::GetHeader() const
182 {
183     return header_;
184 }
185 
SetHeader(ElfW (Ehdr)header)186 void DfxElf::SetHeader(ElfW(Ehdr) header)
187 {
188     header_ = header;
189 }
190 
GetInfos() const191 std::vector<ElfLoadInfo> DfxElf::GetInfos() const
192 {
193     return infos_;
194 }
SetInfos(const std::vector<ElfLoadInfo> & infos)195 void DfxElf::SetInfos(const std::vector<ElfLoadInfo> &infos)
196 {
197     infos_ = infos;
198 }
199 
GetFd() const200 int32_t DfxElf::GetFd() const
201 {
202     return fd_;
203 }
204 
SetFd(int32_t fdValue)205 void DfxElf::SetFd(int32_t fdValue)
206 {
207     fd_ = fdValue;
208 }
209 
GetLoadBias() const210 size_t DfxElf::GetLoadBias() const
211 {
212     return loadBias_;
213 }
214 
SetLoadBias(size_t loadBias)215 void DfxElf::SetLoadBias(size_t loadBias)
216 {
217     loadBias_ = loadBias;
218 }
219 
GetSize() const220 uint64_t DfxElf::GetSize() const
221 {
222     return size_;
223 }
224 
SetSize(uint64_t size)225 void DfxElf::SetSize(uint64_t size)
226 {
227     size_ = size;
228 }
229 } // namespace HiviewDFX
230 } // namespace OHOS
231