1800b99b8Sopenharmony_ci/*
2800b99b8Sopenharmony_ci * Copyright (c) 2022-2024 Huawei Device Co., Ltd.
3800b99b8Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4800b99b8Sopenharmony_ci * you may not use this file except in compliance with the License.
5800b99b8Sopenharmony_ci * You may obtain a copy of the License at
6800b99b8Sopenharmony_ci *
7800b99b8Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
8800b99b8Sopenharmony_ci *
9800b99b8Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10800b99b8Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11800b99b8Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12800b99b8Sopenharmony_ci * See the License for the specific language governing permissions and
13800b99b8Sopenharmony_ci * limitations under the License.
14800b99b8Sopenharmony_ci */
15800b99b8Sopenharmony_ci#ifndef DFX_SYMBOL_H
16800b99b8Sopenharmony_ci#define DFX_SYMBOL_H
17800b99b8Sopenharmony_ci
18800b99b8Sopenharmony_ci#include <cstdint>
19800b99b8Sopenharmony_ci#include <iomanip>
20800b99b8Sopenharmony_ci#include <sstream>
21800b99b8Sopenharmony_ci#include <string>
22800b99b8Sopenharmony_ci#include <vector>
23800b99b8Sopenharmony_ci#include "string_view_util.h"
24800b99b8Sopenharmony_ci
25800b99b8Sopenharmony_cinamespace OHOS {
26800b99b8Sopenharmony_cinamespace HiviewDFX {
27800b99b8Sopenharmony_cistruct DfxSymbol {
28800b99b8Sopenharmony_ci    uint64_t funcVaddr_ = 0;
29800b99b8Sopenharmony_ci    uint64_t offsetToVaddr_ = 0;
30800b99b8Sopenharmony_ci    uint64_t fileVaddr_ = 0;
31800b99b8Sopenharmony_ci    uint64_t taskVaddr_ = 0;
32800b99b8Sopenharmony_ci    uint64_t size_ = 0;
33800b99b8Sopenharmony_ci    uint32_t filePathId_ = 0; // for memMpaItem filePathId_
34800b99b8Sopenharmony_ci    uint32_t symbolNameId_ = 0; // for symbolName_ id
35800b99b8Sopenharmony_ci    int32_t symbolFileIndex_ = -1; // symbols file index, used to report protobuf file
36800b99b8Sopenharmony_ci    int32_t index_ = -1;
37800b99b8Sopenharmony_ci    uint32_t symbolId_ = 0; // for frame map id
38800b99b8Sopenharmony_ci    STRING_VIEW name_ = "";
39800b99b8Sopenharmony_ci    STRING_VIEW demangle_ = ""; // demangle string
40800b99b8Sopenharmony_ci    STRING_VIEW module_ = "";   // maybe empty
41800b99b8Sopenharmony_ci    STRING_VIEW comm_ = "";     // we need a comm name like comm@0x1234
42800b99b8Sopenharmony_ci    STRING_VIEW symbolName_ = "";
43800b99b8Sopenharmony_ci    mutable STRING_VIEW unknow_ = "";
44800b99b8Sopenharmony_ci    uint64_t offset_ = 0;
45800b99b8Sopenharmony_ci    mutable bool matched_ = false; // if some callstack match this
46800b99b8Sopenharmony_ci    int32_t hit_ = 0;
47800b99b8Sopenharmony_ci
48800b99b8Sopenharmony_ci    // elf use this
49800b99b8Sopenharmony_ci    DfxSymbol(uint64_t vaddr, uint64_t size, const std::string &name, const std::string &demangle,
50800b99b8Sopenharmony_ci              const std::string module)
51800b99b8Sopenharmony_ci        : funcVaddr_(vaddr),
52800b99b8Sopenharmony_ci          fileVaddr_(vaddr),
53800b99b8Sopenharmony_ci          size_(size),
54800b99b8Sopenharmony_ci          name_(StringViewHold::Get().Hold(name)),
55800b99b8Sopenharmony_ci          demangle_(StringViewHold::Get().Hold(demangle)),
56800b99b8Sopenharmony_ci          module_(StringViewHold::Get().Hold(module)) {}
57800b99b8Sopenharmony_ci    DfxSymbol(uint64_t vaddr, uint64_t size, const std::string &name, const std::string &module)
58800b99b8Sopenharmony_ci        : DfxSymbol(vaddr, size, name, name, module) {}
59800b99b8Sopenharmony_ci
60800b99b8Sopenharmony_ci    // kernel use this
61800b99b8Sopenharmony_ci    DfxSymbol(uint64_t vaddr, const std::string &name, const std::string &module)
62800b99b8Sopenharmony_ci        : DfxSymbol(vaddr, 0, name, name, module) {}
63800b99b8Sopenharmony_ci
64800b99b8Sopenharmony_ci    // Symbolic use this
65800b99b8Sopenharmony_ci    DfxSymbol(uint64_t taskVaddr = 0, const std::string &comm = "")
66800b99b8Sopenharmony_ci        : taskVaddr_(taskVaddr), comm_(comm) {}
67800b99b8Sopenharmony_ci
68800b99b8Sopenharmony_ci    DfxSymbol(const DfxSymbol &other) = default;
69800b99b8Sopenharmony_ci
70800b99b8Sopenharmony_ci    DfxSymbol& operator=(const DfxSymbol& other) = default;
71800b99b8Sopenharmony_ci
72800b99b8Sopenharmony_ci    inline bool Equal(const DfxSymbol &b) const
73800b99b8Sopenharmony_ci    {
74800b99b8Sopenharmony_ci        return ((funcVaddr_ == b.funcVaddr_) && (demangle_ == b.demangle_));
75800b99b8Sopenharmony_ci    }
76800b99b8Sopenharmony_ci
77800b99b8Sopenharmony_ci    inline bool operator==(const DfxSymbol &b) const
78800b99b8Sopenharmony_ci    {
79800b99b8Sopenharmony_ci        return Equal(b);
80800b99b8Sopenharmony_ci    }
81800b99b8Sopenharmony_ci
82800b99b8Sopenharmony_ci    inline bool operator!=(const DfxSymbol &b) const
83800b99b8Sopenharmony_ci    {
84800b99b8Sopenharmony_ci        return !Equal(b);
85800b99b8Sopenharmony_ci    }
86800b99b8Sopenharmony_ci
87800b99b8Sopenharmony_ci    inline bool IsValid() const
88800b99b8Sopenharmony_ci    {
89800b99b8Sopenharmony_ci        return !module_.empty();
90800b99b8Sopenharmony_ci    }
91800b99b8Sopenharmony_ci    void SetMatchFlag() const
92800b99b8Sopenharmony_ci    {
93800b99b8Sopenharmony_ci        matched_ = true;
94800b99b8Sopenharmony_ci    }
95800b99b8Sopenharmony_ci
96800b99b8Sopenharmony_ci    bool HasMatched() const
97800b99b8Sopenharmony_ci    {
98800b99b8Sopenharmony_ci        return matched_;
99800b99b8Sopenharmony_ci    }
100800b99b8Sopenharmony_ci
101800b99b8Sopenharmony_ci    void SetIpVAddress(uint64_t vaddr)
102800b99b8Sopenharmony_ci    {
103800b99b8Sopenharmony_ci        fileVaddr_ = vaddr;
104800b99b8Sopenharmony_ci        offset_ = fileVaddr_ - funcVaddr_;
105800b99b8Sopenharmony_ci    }
106800b99b8Sopenharmony_ci
107800b99b8Sopenharmony_ci    STRING_VIEW GetName() const
108800b99b8Sopenharmony_ci    {
109800b99b8Sopenharmony_ci        if (!demangle_.empty()) {
110800b99b8Sopenharmony_ci            return demangle_;
111800b99b8Sopenharmony_ci        }
112800b99b8Sopenharmony_ci        if (!name_.empty()) {
113800b99b8Sopenharmony_ci            return name_;
114800b99b8Sopenharmony_ci        }
115800b99b8Sopenharmony_ci        if (unknow_.empty()) {
116800b99b8Sopenharmony_ci            std::stringstream ss;
117800b99b8Sopenharmony_ci            if (!module_.empty()) {
118800b99b8Sopenharmony_ci                ss << module_ << "+0x" << std::hex << fileVaddr_;
119800b99b8Sopenharmony_ci            } else {
120800b99b8Sopenharmony_ci                ss << comm_ << "@0x" << std::hex << taskVaddr_;
121800b99b8Sopenharmony_ci            }
122800b99b8Sopenharmony_ci            unknow_ = StringViewHold::Get().Hold(ss.str());
123800b99b8Sopenharmony_ci        }
124800b99b8Sopenharmony_ci        return unknow_;
125800b99b8Sopenharmony_ci    }
126800b99b8Sopenharmony_ci
127800b99b8Sopenharmony_ci    inline std::string ToString() const
128800b99b8Sopenharmony_ci    {
129800b99b8Sopenharmony_ci        std::stringstream ss;
130800b99b8Sopenharmony_ci        if (fileVaddr_ != 0) {
131800b99b8Sopenharmony_ci            ss << "0x" << std::hex << fileVaddr_;
132800b99b8Sopenharmony_ci        } else {
133800b99b8Sopenharmony_ci            ss << "0x" << std::hex << taskVaddr_;
134800b99b8Sopenharmony_ci        }
135800b99b8Sopenharmony_ci        ss << " " << GetName();
136800b99b8Sopenharmony_ci        return ss.str();
137800b99b8Sopenharmony_ci    };
138800b99b8Sopenharmony_ci
139800b99b8Sopenharmony_ci    std::string ToDebugString() const
140800b99b8Sopenharmony_ci    {
141800b99b8Sopenharmony_ci        std::stringstream ss;
142800b99b8Sopenharmony_ci        ss << "0x" << std::setfill('0') << std::setw(sizeof(funcVaddr_) * 2); // 2 : a multiplicand
143800b99b8Sopenharmony_ci        ss << std::hex << funcVaddr_;
144800b99b8Sopenharmony_ci        ss << "|";
145800b99b8Sopenharmony_ci        ss << std::setfill('0') << std::setw(sizeof(size_)) << size_;
146800b99b8Sopenharmony_ci        ss << "|";
147800b99b8Sopenharmony_ci        ss << demangle_ << "|";
148800b99b8Sopenharmony_ci        ss << name_ << "|";
149800b99b8Sopenharmony_ci        ss << (matched_ ? "matched" : "");
150800b99b8Sopenharmony_ci        ss << " unknowname:" << unknow_.size();
151800b99b8Sopenharmony_ci        ss << " task:" << (comm_.size() > 0 ? comm_ : "");
152800b99b8Sopenharmony_ci        ss << "@" << taskVaddr_;
153800b99b8Sopenharmony_ci        ss << " file:" << (module_.size() > 0 ? module_ : "");
154800b99b8Sopenharmony_ci        ss << "@" << fileVaddr_;
155800b99b8Sopenharmony_ci        return ss.str();
156800b99b8Sopenharmony_ci    };
157800b99b8Sopenharmony_ci
158800b99b8Sopenharmony_ci    inline bool Contain(uint64_t addr) const
159800b99b8Sopenharmony_ci    {
160800b99b8Sopenharmony_ci        if (size_ == 0) {
161800b99b8Sopenharmony_ci            return funcVaddr_ <= addr;
162800b99b8Sopenharmony_ci        } else {
163800b99b8Sopenharmony_ci            return (funcVaddr_ <= addr) && ((funcVaddr_ + size_) > addr);
164800b99b8Sopenharmony_ci        }
165800b99b8Sopenharmony_ci    }
166800b99b8Sopenharmony_ci
167800b99b8Sopenharmony_ci    // The range [first, last) must be partitioned with respect to the expression
168800b99b8Sopenharmony_ci    // !(value < element) or !comp(value, element)
169800b99b8Sopenharmony_ci    static bool ValueLessThen(uint64_t vaddr, const DfxSymbol &a)
170800b99b8Sopenharmony_ci    {
171800b99b8Sopenharmony_ci        return vaddr < a.funcVaddr_;
172800b99b8Sopenharmony_ci    }
173800b99b8Sopenharmony_ci
174800b99b8Sopenharmony_ci    static bool ValueLessEqual(uint64_t vaddr, const DfxSymbol &a)
175800b99b8Sopenharmony_ci    {
176800b99b8Sopenharmony_ci        return vaddr <= a.funcVaddr_;
177800b99b8Sopenharmony_ci    }
178800b99b8Sopenharmony_ci};
179800b99b8Sopenharmony_ci} // namespace HiviewDFX
180800b99b8Sopenharmony_ci} // namespace OHOS
181800b99b8Sopenharmony_ci#endif
182