1 /*
2 * Copyright (c) 2022 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 "hiebpf_data_file.h"
17
18 #include <vector>
19
20 #include "kernel_symbol_info.h"
21
22
MakeShared(const std::string & cmd,const std::string & filename,const std::size_t pages)23 std::shared_ptr<HiebpfDataFile> HiebpfDataFile::MakeShared(
24 const std::string& cmd,
25 const std::string& filename,
26 const std::size_t pages)
27 {
28 std::shared_ptr<HiebpfDataFile> obj {new(std::nothrow) HiebpfDataFile {cmd, filename, pages}};
29 CHECK_NOTNULL(obj, nullptr, "failed to make HiebpfDataFile");
30 CHECK_TRUE(obj->OpenFile() == 0, nullptr, "failed to open hiebpf data file");
31 CHECK_TRUE(obj->MapFile() == 0, nullptr, "failed to map hiebpf data file into memory");
32 return obj;
33 }
34
Reserve(const std::size_t size)35 void* HiebpfDataFile::Reserve(const std::size_t size)
36 {
37 std::lock_guard<std::mutex> lk {mtx_};
38 if (offset_ + size >= length_) {
39 if (RemapFile(size) != 0) {
40 return nullptr;
41 }
42 }
43
44 if (mapAddr_ == nullptr) {
45 return nullptr;
46 }
47 char* buffer = static_cast<char *>(mapAddr_);
48 buffer += offset_;
49 (void)memset_s(buffer, size, 0, size);
50 uint32_t *tracer = reinterpret_cast<uint32_t *>(buffer);
51 (*tracer) = BADTRACE;
52 uint32_t *len = tracer + 1;
53 (*len) = size - sizeof(uint32_t) * 2; // 2: double
54 offset_ += size;
55 return buffer;
56 }
57
Discard(void * data)58 void HiebpfDataFile::Discard(void *data)
59 {
60 if (data) {
61 int64_t interval = static_cast<int64_t>((__u64)data) - ((__u64)mapAddr_);
62 if (0 <= interval and static_cast<uint64_t>(interval) < length_) {
63 uint32_t *tracer = static_cast<uint32_t*>(data);
64 (*tracer) = BADTRACE;
65 }
66 }
67 }
68
WriteKernelSymbol()69 void HiebpfDataFile::WriteKernelSymbol()
70 {
71 std::vector<uint8_t> buf;
72 uint32_t bufSize = OHOS::Developtools::Hiebpf::KernelSymbolInfo::GetSymbolData(buf);
73 char *tmp = static_cast<char *>(Reserve(bufSize + sizeof(uint32_t) * 2));
74 if (tmp == nullptr) {
75 return;
76 }
77 uint32_t *type = reinterpret_cast<uint32_t *>(tmp);
78 (*type) = KERNEL_SYM;
79 uint32_t *len = type + 1;
80 (*len) = bufSize;
81 if (memcpy_s(tmp + sizeof(uint32_t) * 2, bufSize, buf.data(), bufSize) != EOK) { // 2: double
82 HHLOGE(true, "failed to memcpy");
83 return;
84 }
85 }
86
Submit(void * data)87 void HiebpfDataFile::Submit(void *data)
88 {
89 __u64 addr = (__u64) data;
90 addr &= ~(pageSize_ - 1);
91 __u32 *len = static_cast<__u32 *>(data);
92 ++len;
93 int ret = msync(reinterpret_cast<void*>(addr), *len, MS_ASYNC);
94 HHLOGF(ret == -1, "failed msync data item with %u bytes", *len);
95 return;
96 }
97
MapFile()98 int HiebpfDataFile::MapFile()
99 {
100 CHECK_TRUE(ExtendFile(mapPos_, length_) == 0, -1,
101 "failed to extend data file from %u with %u bytes", mapPos_, length_);
102 HHLOGI(true, "done extending the data file");
103 // map the file
104 mapAddr_ = mmap(
105 nullptr, length_,
106 PROT_WRITE | PROT_READ, MAP_SHARED | MAP_POPULATE,
107 fd_, mapPos_);
108 CHECK_TRUE(mapAddr_ != MAP_FAILED, -1, "mmap() failed: %s", strerror(errno));
109 HHLOGI(true, "done mem mapping hiebpf data file");
110 // hiebpf data file header
111 CHECK_TRUE(WriteFileHeader() == 0, -1, "failed to write hiebpf data file header");
112 HHLOGI(true, "done writing hiebpf data file header");
113 return 0;
114 }
115
RemapFile(const std::size_t size)116 int HiebpfDataFile::RemapFile(const std::size_t size)
117 {
118 if (munmap(mapAddr_, length_) != 0) {
119 return -1;
120 }
121 std::size_t curPos = mapPos_ + offset_;
122 std::size_t remapPos = curPos & ~(pageSize_ - 1);
123 std::size_t remapOff = curPos - remapPos;
124
125 size_t extendLength = DEFAULT_MMAP_LENGTH;
126 while (remapOff + size > extendLength) {
127 extendLength += DEFAULT_MMAP_LENGTH;
128 }
129
130 CHECK_TRUE(ExtendFile(remapPos, extendLength) == 0, -1,
131 "failed to extend file from %u with %u bytes", remapPos, length_);
132 HHLOGI(true, "done extending the data file");
133 mapAddr_ = mmap(
134 nullptr, extendLength,
135 PROT_WRITE | PROT_READ, MAP_SHARED | MAP_POPULATE,
136 fd_, remapPos);
137 CHECK_TRUE(mapAddr_ != MAP_FAILED, -1, "failed to remap data file from %u to %u", mapPos_, remapPos);
138 HHLOGI(true, "done remapping data file from %u, to %u", mapPos_, remapPos);
139 mapPos_ = remapPos;
140 offset_ = remapOff;
141 length_ = extendLength;
142 return 0;
143 }