1b1994897Sopenharmony_ci/**
2b1994897Sopenharmony_ci * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3b1994897Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4b1994897Sopenharmony_ci * you may not use this file except in compliance with the License.
5b1994897Sopenharmony_ci * You may obtain a copy of the License at
6b1994897Sopenharmony_ci *
7b1994897Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
8b1994897Sopenharmony_ci *
9b1994897Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10b1994897Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11b1994897Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12b1994897Sopenharmony_ci * See the License for the specific language governing permissions and
13b1994897Sopenharmony_ci * limitations under the License.
14b1994897Sopenharmony_ci */
15b1994897Sopenharmony_ci
16b1994897Sopenharmony_ci#ifndef LIBPANDABASE_OS_DEBUG_INFO_H
17b1994897Sopenharmony_ci#define LIBPANDABASE_OS_DEBUG_INFO_H
18b1994897Sopenharmony_ci
19b1994897Sopenharmony_ci#include <set>
20b1994897Sopenharmony_ci#include <list>
21b1994897Sopenharmony_ci#include <string>
22b1994897Sopenharmony_ci#include <libdwarf/libdwarf.h>
23b1994897Sopenharmony_ci#include "macros.h"
24b1994897Sopenharmony_ci#include "utils/span.h"
25b1994897Sopenharmony_ci
26b1994897Sopenharmony_cinamespace panda {
27b1994897Sopenharmony_ci
28b1994897Sopenharmony_ciclass DebugInfo {
29b1994897Sopenharmony_cipublic:
30b1994897Sopenharmony_ci    enum ErrorCode { SUCCESS, NO_DEBUG_INFO, ERROR };
31b1994897Sopenharmony_ci
32b1994897Sopenharmony_ci    explicit DebugInfo() = default;
33b1994897Sopenharmony_ci
34b1994897Sopenharmony_ci    ~DebugInfo()
35b1994897Sopenharmony_ci    {
36b1994897Sopenharmony_ci        Destroy();
37b1994897Sopenharmony_ci    }
38b1994897Sopenharmony_ci
39b1994897Sopenharmony_ci    ErrorCode ReadFromFile(const char *filename);
40b1994897Sopenharmony_ci
41b1994897Sopenharmony_ci    /*
42b1994897Sopenharmony_ci     * Find location (name, source file, line) of the specified pc in source code
43b1994897Sopenharmony_ci     */
44b1994897Sopenharmony_ci    bool GetSrcLocation(uintptr_t pc, std::string *function, std::string *src_file, uint32_t *line);
45b1994897Sopenharmony_ci
46b1994897Sopenharmony_ci    void Destroy();
47b1994897Sopenharmony_ci
48b1994897Sopenharmony_ci    DEFAULT_MOVE_SEMANTIC(DebugInfo);
49b1994897Sopenharmony_ci    NO_COPY_SEMANTIC(DebugInfo);
50b1994897Sopenharmony_ci
51b1994897Sopenharmony_ciprivate:
52b1994897Sopenharmony_ci    /**
53b1994897Sopenharmony_ci     * Cache entry for a compilation unit (object file).
54b1994897Sopenharmony_ci     * It contains the pointer to the corresponding DIE (Debug Information Entity),
55b1994897Sopenharmony_ci     * offset of the DIE in .debug_info, decoded line numbers for the compilation unit
56b1994897Sopenharmony_ci     * and function cache.
57b1994897Sopenharmony_ci     */
58b1994897Sopenharmony_ci    class CompUnit {
59b1994897Sopenharmony_ci    public:
60b1994897Sopenharmony_ci        CompUnit(Dwarf_Die cu_die, Dwarf_Debug dbg) : dbg_(dbg), cu_die_(cu_die) {}
61b1994897Sopenharmony_ci
62b1994897Sopenharmony_ci        CompUnit(CompUnit &&e) : dbg_(e.dbg_), cu_die_(e.cu_die_), line_ctx_(e.line_ctx_)
63b1994897Sopenharmony_ci        {
64b1994897Sopenharmony_ci            e.cu_die_ = nullptr;
65b1994897Sopenharmony_ci            e.line_ctx_ = nullptr;
66b1994897Sopenharmony_ci        }
67b1994897Sopenharmony_ci
68b1994897Sopenharmony_ci        ~CompUnit();
69b1994897Sopenharmony_ci
70b1994897Sopenharmony_ci        CompUnit &operator=(CompUnit &&e)
71b1994897Sopenharmony_ci        {
72b1994897Sopenharmony_ci            dbg_ = e.dbg_;
73b1994897Sopenharmony_ci            cu_die_ = e.cu_die_;
74b1994897Sopenharmony_ci            e.cu_die_ = nullptr;
75b1994897Sopenharmony_ci            line_ctx_ = e.line_ctx_;
76b1994897Sopenharmony_ci            e.line_ctx_ = nullptr;
77b1994897Sopenharmony_ci            return *this;
78b1994897Sopenharmony_ci        }
79b1994897Sopenharmony_ci
80b1994897Sopenharmony_ci        Dwarf_Die GetDie() const
81b1994897Sopenharmony_ci        {
82b1994897Sopenharmony_ci            return cu_die_;
83b1994897Sopenharmony_ci        }
84b1994897Sopenharmony_ci
85b1994897Sopenharmony_ci        Dwarf_Line_Context GetLineContext();
86b1994897Sopenharmony_ci
87b1994897Sopenharmony_ci        NO_COPY_SEMANTIC(CompUnit);
88b1994897Sopenharmony_ci
89b1994897Sopenharmony_ci    private:
90b1994897Sopenharmony_ci        Dwarf_Debug dbg_;
91b1994897Sopenharmony_ci        Dwarf_Die cu_die_;
92b1994897Sopenharmony_ci        Dwarf_Line_Context line_ctx_ {nullptr};
93b1994897Sopenharmony_ci    };
94b1994897Sopenharmony_ci
95b1994897Sopenharmony_ci    class Range {
96b1994897Sopenharmony_ci    public:
97b1994897Sopenharmony_ci        Range(Dwarf_Addr low_pc, Dwarf_Addr high_pc, CompUnit *cu = nullptr,
98b1994897Sopenharmony_ci              const std::string &function = std::string())  // NOLINT(modernize-pass-by-value)
99b1994897Sopenharmony_ci            : low_pc_(low_pc), high_pc_(high_pc), cu_(cu), function_(function)
100b1994897Sopenharmony_ci        {
101b1994897Sopenharmony_ci        }
102b1994897Sopenharmony_ci
103b1994897Sopenharmony_ci        Dwarf_Addr GetLowPc() const
104b1994897Sopenharmony_ci        {
105b1994897Sopenharmony_ci            return low_pc_;
106b1994897Sopenharmony_ci        }
107b1994897Sopenharmony_ci
108b1994897Sopenharmony_ci        Dwarf_Addr GetHighPc() const
109b1994897Sopenharmony_ci        {
110b1994897Sopenharmony_ci            return high_pc_;
111b1994897Sopenharmony_ci        }
112b1994897Sopenharmony_ci
113b1994897Sopenharmony_ci        bool Contain(Dwarf_Addr addr) const
114b1994897Sopenharmony_ci        {
115b1994897Sopenharmony_ci            return low_pc_ <= addr && addr < high_pc_;
116b1994897Sopenharmony_ci        }
117b1994897Sopenharmony_ci
118b1994897Sopenharmony_ci        bool Contain(const Range &r) const
119b1994897Sopenharmony_ci        {
120b1994897Sopenharmony_ci            return low_pc_ <= r.low_pc_ && r.high_pc_ <= high_pc_;
121b1994897Sopenharmony_ci        }
122b1994897Sopenharmony_ci
123b1994897Sopenharmony_ci        CompUnit *GetCu() const
124b1994897Sopenharmony_ci        {
125b1994897Sopenharmony_ci            return cu_;
126b1994897Sopenharmony_ci        }
127b1994897Sopenharmony_ci
128b1994897Sopenharmony_ci        std::string GetFunction() const
129b1994897Sopenharmony_ci        {
130b1994897Sopenharmony_ci            return function_;
131b1994897Sopenharmony_ci        }
132b1994897Sopenharmony_ci
133b1994897Sopenharmony_ci        void SetFunction(const std::string &function)
134b1994897Sopenharmony_ci        {
135b1994897Sopenharmony_ci            this->function_ = function;
136b1994897Sopenharmony_ci        }
137b1994897Sopenharmony_ci
138b1994897Sopenharmony_ci        bool operator<(const Range &r) const
139b1994897Sopenharmony_ci        {
140b1994897Sopenharmony_ci            return high_pc_ < r.high_pc_;
141b1994897Sopenharmony_ci        }
142b1994897Sopenharmony_ci
143b1994897Sopenharmony_ci        bool operator==(const Range &r) const
144b1994897Sopenharmony_ci        {
145b1994897Sopenharmony_ci            return low_pc_ == r.low_pc_ && high_pc_ == r.high_pc_;
146b1994897Sopenharmony_ci        }
147b1994897Sopenharmony_ci
148b1994897Sopenharmony_ci    private:
149b1994897Sopenharmony_ci        Dwarf_Addr low_pc_;
150b1994897Sopenharmony_ci        Dwarf_Addr high_pc_;
151b1994897Sopenharmony_ci        CompUnit *cu_ = nullptr;
152b1994897Sopenharmony_ci        std::string function_;
153b1994897Sopenharmony_ci    };
154b1994897Sopenharmony_ci
155b1994897Sopenharmony_ciprivate:
156b1994897Sopenharmony_ci    bool FindCompUnitByPc(uintptr_t pc, Dwarf_Die *cu_die);
157b1994897Sopenharmony_ci    void TraverseChildren(CompUnit *cu, Dwarf_Die die);
158b1994897Sopenharmony_ci    void TraverseSiblings(CompUnit *cu, Dwarf_Die die);
159b1994897Sopenharmony_ci    void GetFunctionName(Dwarf_Die die, std::string *function);
160b1994897Sopenharmony_ci    void AddFunction(CompUnit *cu, Dwarf_Addr low_pc, Dwarf_Addr high_pc, const std::string &function);
161b1994897Sopenharmony_ci    bool GetSrcFileAndLine(uintptr_t pc, Dwarf_Line_Context line_ctx, std::string *src_file, uint32_t *line);
162b1994897Sopenharmony_ci    Dwarf_Line GetLastLineWithPc(Dwarf_Addr pc, Span<Dwarf_Line>::ConstIterator it,
163b1994897Sopenharmony_ci                                 Span<Dwarf_Line>::ConstIterator end);
164b1994897Sopenharmony_ci    void GetSrcFileAndLine(Dwarf_Line line, std::string *out_src_file, uint32_t *out_line);
165b1994897Sopenharmony_ci    bool PcMatches(uintptr_t pc, Dwarf_Die die);
166b1994897Sopenharmony_ci    bool GetDieRange(Dwarf_Die die, Dwarf_Addr *out_low_pc, Dwarf_Addr *out_high_pc);
167b1994897Sopenharmony_ci    bool GetDieRangeForPc(uintptr_t pc, Dwarf_Die die, Dwarf_Addr *out_low_pc, Dwarf_Addr *out_high_pc);
168b1994897Sopenharmony_ci    bool FindRangeForPc(uintptr_t pc, const Span<Dwarf_Ranges> &ranges, Dwarf_Addr base_addr, Dwarf_Addr *out_low_pc,
169b1994897Sopenharmony_ci                        Dwarf_Addr *out_high_pc);
170b1994897Sopenharmony_ci
171b1994897Sopenharmony_ciprivate:
172b1994897Sopenharmony_ci    static constexpr int INVALID_FD = -1;
173b1994897Sopenharmony_ci
174b1994897Sopenharmony_ci    int fd_ {INVALID_FD};
175b1994897Sopenharmony_ci    Dwarf_Debug dbg_ {nullptr};
176b1994897Sopenharmony_ci    Dwarf_Arange *aranges_ {nullptr};
177b1994897Sopenharmony_ci    Dwarf_Signed arange_count_ {0};
178b1994897Sopenharmony_ci    std::list<CompUnit> cu_list_;
179b1994897Sopenharmony_ci    std::set<Range> ranges_;
180b1994897Sopenharmony_ci};
181b1994897Sopenharmony_ci
182b1994897Sopenharmony_ci}  // namespace panda
183b1994897Sopenharmony_ci
184b1994897Sopenharmony_ci#endif  // LIBPANDABASE_OS_DEBUG_INFO_H
185