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