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 #include <elf_parser.h>
17
18 namespace OHOS {
19 namespace Developtools {
20 namespace NativeDaemon {
21 namespace ELF {
MakeUnique(unsigned char * const ehdrBuf,const std::size_t bufSize)22 std::unique_ptr<ElfHeader> ElfHeader::MakeUnique(unsigned char * const ehdrBuf,
23 const std::size_t bufSize)
24 {
25 std::unique_ptr<ElfHeader> ehdr {new (std::nothrow) ElfHeader()};
26 if (ehdr == nullptr) {
27 HLOGV("ElfHeader() failed");
28 return nullptr;
29 }
30 if (!ehdr->Init(ehdrBuf, bufSize)) {
31 HLOGV("ElfHeader::Init(ehdrBuf, bufSize) failed\n");
32 DumpEhdrBuf(reinterpret_cast<char *>(ehdrBuf), bufSize);
33 return nullptr;
34 }
35 return ehdr;
36 }
37
Init(unsigned char * const ehdrBuf,const std::size_t bufSize)38 bool ElfHeader::Init(unsigned char * const ehdrBuf, const std::size_t bufSize)
39 {
40 std::string magicStr {ehdrBuf, ehdrBuf + SELFMAG};
41 std::string elfMagic {ELFMAG};
42 if (magicStr.compare(elfMagic) != 0) {
43 HLOGE("elf magic not found");
44 return false;
45 }
46 if (memcpy_s(ehdrIdent_, EI_NIDENT, ehdrBuf, EI_NIDENT) != EOK) {
47 HLOGE("init ehdrIdent_ failed");
48 return false;
49 }
50 if (ehdrBuf[EI_CLASS] == ELFCLASS32 and ParseElf32Header(ehdrBuf, bufSize)) {
51 return true;
52 }
53 if (ehdrBuf[EI_CLASS] == ELFCLASS64 and ParseElf64Header(ehdrBuf, bufSize)) {
54 return true;
55 }
56 HLOGE("init elf header failed, elf header buffer dumped");
57 return false;
58 }
59
ParseElf32Header(unsigned char * const ehdrBuf,const std::size_t bufSize)60 bool ElfHeader::ParseElf32Header(unsigned char * const ehdrBuf, const std::size_t bufSize)
61 {
62 if (bufSize < ehdr32Size) {
63 HLOGE("bad elf32 header buffer");
64 return false;
65 }
66 size_t curIndex {EI_NIDENT};
67 uint16_t *u2Buf = reinterpret_cast<uint16_t *>(ehdrBuf + curIndex);
68 type_ = u2Buf[0];
69 curIndex += sizeof(uint16_t);
70
71 u2Buf = reinterpret_cast<uint16_t *>(ehdrBuf + curIndex);
72 machine_ = u2Buf[0];
73 curIndex += sizeof(uint16_t);
74
75 uint32_t *u4Buf = reinterpret_cast<uint32_t *>(ehdrBuf + curIndex);
76 elfVersion_ = u4Buf[0];
77 curIndex += sizeof(uint32_t);
78
79 u4Buf = reinterpret_cast<uint32_t *>(ehdrBuf + curIndex);
80 prgEntryVaddr_ = u4Buf[0];
81 curIndex += sizeof(uint32_t);
82
83 u4Buf = reinterpret_cast<uint32_t *>(ehdrBuf + curIndex);
84 phdrOffset_ = u4Buf[0];
85 curIndex += sizeof(uint32_t);
86
87 u4Buf = reinterpret_cast<uint32_t *>(ehdrBuf + curIndex);
88 shdrOffset_ = u4Buf[0];
89 curIndex += sizeof(uint32_t);
90
91 u4Buf = reinterpret_cast<uint32_t *>(ehdrBuf + curIndex);
92 ehdrFlags_ = u4Buf[0];
93 curIndex += sizeof(uint32_t);
94
95 u2Buf = reinterpret_cast<uint16_t *>(ehdrBuf + curIndex);
96 ehdrSize_ = u2Buf[0];
97 curIndex += sizeof(uint16_t);
98
99 u2Buf = reinterpret_cast<uint16_t *>(ehdrBuf + curIndex);
100 phdrEntSize_ = u2Buf[0];
101 curIndex += sizeof(uint16_t);
102
103 u2Buf = reinterpret_cast<uint16_t *>(ehdrBuf + curIndex);
104 phdrNumEnts_ = u2Buf[0];
105 curIndex += sizeof(uint16_t);
106
107 u2Buf = reinterpret_cast<uint16_t *>(ehdrBuf + curIndex);
108 shdrEntSize_ = u2Buf[0];
109 curIndex += sizeof(uint16_t);
110
111 u2Buf = reinterpret_cast<uint16_t *>(ehdrBuf + curIndex);
112 shdrNumEnts_ = u2Buf[0];
113 curIndex += sizeof(uint16_t);
114
115 u2Buf = reinterpret_cast<uint16_t *>(ehdrBuf + curIndex);
116 shdrStrTabIdx_ = u2Buf[0];
117
118 #ifdef HIPERF_DEBUG_ASSERT
119 curIndex += sizeof(uint16_t);
120 HLOG_ASSERT(curIndex == ehdrSize_);
121 HLOG_ASSERT(shdr32Size == ehdrSize_);
122 #endif
123 return true;
124 }
125
ParseElf64Header(unsigned char * const ehdrBuf,const std::size_t bufSize)126 bool ElfHeader::ParseElf64Header(unsigned char * const ehdrBuf, const std::size_t bufSize)
127 {
128 if (bufSize < ehdr64Size) {
129 HLOGE("bad elf64 header buffer");
130 return false;
131 }
132 size_t curIndex {EI_NIDENT};
133 uint16_t *u2Buf = reinterpret_cast<uint16_t *>(ehdrBuf + curIndex);
134 type_ = u2Buf[0];
135 curIndex += sizeof(uint16_t);
136
137 u2Buf = reinterpret_cast<uint16_t *>(ehdrBuf + curIndex);
138 machine_ = u2Buf[0];
139 curIndex += sizeof(uint16_t);
140
141 uint32_t *u4Buf = reinterpret_cast<uint32_t *>(ehdrBuf + curIndex);
142 elfVersion_ = u4Buf[0];
143 curIndex += sizeof(uint32_t);
144
145 uint64_t *u8Buf = reinterpret_cast<uint64_t *>(ehdrBuf + curIndex);
146 prgEntryVaddr_ = u8Buf[0];
147 curIndex += sizeof(uint64_t);
148
149 u8Buf = reinterpret_cast<uint64_t *>(ehdrBuf + curIndex);
150 phdrOffset_ = u8Buf[0];
151 curIndex += sizeof(uint64_t);
152
153 u8Buf = reinterpret_cast<uint64_t *>(ehdrBuf + curIndex);
154 shdrOffset_ = u8Buf[0];
155 curIndex += sizeof(uint64_t);
156
157 u4Buf = reinterpret_cast<uint32_t *>(ehdrBuf + curIndex);
158 ehdrFlags_ = u4Buf[0];
159 curIndex += sizeof(uint32_t);
160
161 u2Buf = reinterpret_cast<uint16_t *>(ehdrBuf + curIndex);
162 ehdrSize_ = u2Buf[0];
163 curIndex += sizeof(uint16_t);
164
165 u2Buf = reinterpret_cast<uint16_t *>(ehdrBuf + curIndex);
166 phdrEntSize_ = u2Buf[0];
167 curIndex += sizeof(uint16_t);
168
169 u2Buf = reinterpret_cast<uint16_t *>(ehdrBuf + curIndex);
170 phdrNumEnts_ = u2Buf[0];
171 curIndex += sizeof(uint16_t);
172
173 u2Buf = reinterpret_cast<uint16_t *>(ehdrBuf + curIndex);
174 shdrEntSize_ = u2Buf[0];
175 curIndex += sizeof(uint16_t);
176
177 u2Buf = reinterpret_cast<uint16_t *>(ehdrBuf + curIndex);
178 shdrNumEnts_ = static_cast<long long>(*u2Buf);
179 curIndex += sizeof(uint16_t);
180
181 u2Buf = reinterpret_cast<uint16_t *>(ehdrBuf + curIndex);
182 shdrStrTabIdx_ = u2Buf[0];
183
184 #ifdef HIPERF_DEBUG_ASSERT
185 curIndex += sizeof(uint16_t);
186 HLOG_ASSERT(curIndex == ehdrSize_);
187 HLOG_ASSERT(shdr64Size == ehdrSize_);
188 #endif
189 return true;
190 }
191 } // namespace ELF
192 } // namespace NativeDaemon
193 } // namespace Developtools
194 } // namespace OHOS