1 /*
2  * Copyright (c) 2022-2024 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 #ifndef DFX_SYMBOL_H
16 #define DFX_SYMBOL_H
17 
18 #include <cstdint>
19 #include <iomanip>
20 #include <sstream>
21 #include <string>
22 #include <vector>
23 #include "string_view_util.h"
24 
25 namespace OHOS {
26 namespace HiviewDFX {
27 struct DfxSymbol {
28     uint64_t funcVaddr_ = 0;
29     uint64_t offsetToVaddr_ = 0;
30     uint64_t fileVaddr_ = 0;
31     uint64_t taskVaddr_ = 0;
32     uint64_t size_ = 0;
33     uint32_t filePathId_ = 0; // for memMpaItem filePathId_
34     uint32_t symbolNameId_ = 0; // for symbolName_ id
35     int32_t symbolFileIndex_ = -1; // symbols file index, used to report protobuf file
36     int32_t index_ = -1;
37     uint32_t symbolId_ = 0; // for frame map id
38     STRING_VIEW name_ = "";
39     STRING_VIEW demangle_ = ""; // demangle string
40     STRING_VIEW module_ = "";   // maybe empty
41     STRING_VIEW comm_ = "";     // we need a comm name like comm@0x1234
42     STRING_VIEW symbolName_ = "";
43     mutable STRING_VIEW unknow_ = "";
44     uint64_t offset_ = 0;
45     mutable bool matched_ = false; // if some callstack match this
46     int32_t hit_ = 0;
47 
48     // elf use this
DfxSymbolDfxSymbol49     DfxSymbol(uint64_t vaddr, uint64_t size, const std::string &name, const std::string &demangle,
50               const std::string module)
51         : funcVaddr_(vaddr),
52           fileVaddr_(vaddr),
53           size_(size),
54           name_(StringViewHold::Get().Hold(name)),
55           demangle_(StringViewHold::Get().Hold(demangle)),
56           module_(StringViewHold::Get().Hold(module)) {}
DfxSymbolDfxSymbol57     DfxSymbol(uint64_t vaddr, uint64_t size, const std::string &name, const std::string &module)
58         : DfxSymbol(vaddr, size, name, name, module) {}
59 
60     // kernel use this
DfxSymbolDfxSymbol61     DfxSymbol(uint64_t vaddr, const std::string &name, const std::string &module)
62         : DfxSymbol(vaddr, 0, name, name, module) {}
63 
64     // Symbolic use this
65     DfxSymbol(uint64_t taskVaddr = 0, const std::string &comm = "")
66         : taskVaddr_(taskVaddr), comm_(comm) {}
67 
68     DfxSymbol(const DfxSymbol &other) = default;
69 
70     DfxSymbol& operator=(const DfxSymbol& other) = default;
71 
EqualDfxSymbol72     inline bool Equal(const DfxSymbol &b) const
73     {
74         return ((funcVaddr_ == b.funcVaddr_) && (demangle_ == b.demangle_));
75     }
76 
77     inline bool operator==(const DfxSymbol &b) const
78     {
79         return Equal(b);
80     }
81 
82     inline bool operator!=(const DfxSymbol &b) const
83     {
84         return !Equal(b);
85     }
86 
IsValidDfxSymbol87     inline bool IsValid() const
88     {
89         return !module_.empty();
90     }
SetMatchFlagDfxSymbol91     void SetMatchFlag() const
92     {
93         matched_ = true;
94     }
95 
HasMatchedDfxSymbol96     bool HasMatched() const
97     {
98         return matched_;
99     }
100 
SetIpVAddressDfxSymbol101     void SetIpVAddress(uint64_t vaddr)
102     {
103         fileVaddr_ = vaddr;
104         offset_ = fileVaddr_ - funcVaddr_;
105     }
106 
GetNameDfxSymbol107     STRING_VIEW GetName() const
108     {
109         if (!demangle_.empty()) {
110             return demangle_;
111         }
112         if (!name_.empty()) {
113             return name_;
114         }
115         if (unknow_.empty()) {
116             std::stringstream ss;
117             if (!module_.empty()) {
118                 ss << module_ << "+0x" << std::hex << fileVaddr_;
119             } else {
120                 ss << comm_ << "@0x" << std::hex << taskVaddr_;
121             }
122             unknow_ = StringViewHold::Get().Hold(ss.str());
123         }
124         return unknow_;
125     }
126 
ToStringDfxSymbol127     inline std::string ToString() const
128     {
129         std::stringstream ss;
130         if (fileVaddr_ != 0) {
131             ss << "0x" << std::hex << fileVaddr_;
132         } else {
133             ss << "0x" << std::hex << taskVaddr_;
134         }
135         ss << " " << GetName();
136         return ss.str();
137     };
138 
ToDebugStringDfxSymbol139     std::string ToDebugString() const
140     {
141         std::stringstream ss;
142         ss << "0x" << std::setfill('0') << std::setw(sizeof(funcVaddr_) * 2); // 2 : a multiplicand
143         ss << std::hex << funcVaddr_;
144         ss << "|";
145         ss << std::setfill('0') << std::setw(sizeof(size_)) << size_;
146         ss << "|";
147         ss << demangle_ << "|";
148         ss << name_ << "|";
149         ss << (matched_ ? "matched" : "");
150         ss << " unknowname:" << unknow_.size();
151         ss << " task:" << (comm_.size() > 0 ? comm_ : "");
152         ss << "@" << taskVaddr_;
153         ss << " file:" << (module_.size() > 0 ? module_ : "");
154         ss << "@" << fileVaddr_;
155         return ss.str();
156     };
157 
ContainDfxSymbol158     inline bool Contain(uint64_t addr) const
159     {
160         if (size_ == 0) {
161             return funcVaddr_ <= addr;
162         } else {
163             return (funcVaddr_ <= addr) && ((funcVaddr_ + size_) > addr);
164         }
165     }
166 
167     // The range [first, last) must be partitioned with respect to the expression
168     // !(value < element) or !comp(value, element)
ValueLessThenDfxSymbol169     static bool ValueLessThen(uint64_t vaddr, const DfxSymbol &a)
170     {
171         return vaddr < a.funcVaddr_;
172     }
173 
ValueLessEqualDfxSymbol174     static bool ValueLessEqual(uint64_t vaddr, const DfxSymbol &a)
175     {
176         return vaddr <= a.funcVaddr_;
177     }
178 };
179 } // namespace HiviewDFX
180 } // namespace OHOS
181 #endif
182