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 16#include "hiebpf_data_file.h" 17 18#include <vector> 19 20#include "kernel_symbol_info.h" 21 22 23std::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 35void* 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 58void 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 69void 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 87void 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 98int 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 116int 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}