• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-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 #ifndef PANDA_DEBUG_INFO_H_
16 #define PANDA_DEBUG_INFO_H_
17 
18 #include <set>
19 #include <list>
20 #include <string>
21 #include <libdwarf/libdwarf.h>
22 #include "macros.h"
23 #include "utils/span.h"
24 
25 namespace panda {
26 
27 class DebugInfo {
28 public:
29     enum ErrorCode { SUCCESS, NO_DEBUG_INFO, ERROR };
30 
31     explicit DebugInfo() = default;
32 
~DebugInfo()33     ~DebugInfo()
34     {
35         Destroy();
36     }
37 
38     ErrorCode ReadFromFile(const char *filename);
39 
40     /*
41      * Find location (name, source file, line) of the specified pc in source code
42      */
43     bool GetSrcLocation(uintptr_t pc, std::string *function, std::string *src_file, uint32_t *line);
44 
45     void Destroy();
46 
47     DEFAULT_MOVE_SEMANTIC(DebugInfo);
48     NO_COPY_SEMANTIC(DebugInfo);
49 
50 private:
51     /**
52      * Cache entry for a compilation unit (object file).
53      * It contains the pointer to the corresponding DIE (Debug Information Entity),
54      * offset of the DIE in .debug_info, decoded line numbers for the compilation unit
55      * and function cache.
56      */
57     class CompUnit {
58     public:
CompUnit(Dwarf_Die cu_die,Dwarf_Debug dbg)59         CompUnit(Dwarf_Die cu_die, Dwarf_Debug dbg) : dbg_(dbg), cu_die_(cu_die) {}
60 
CompUnit(CompUnit && e)61         CompUnit(CompUnit &&e) : dbg_(e.dbg_), cu_die_(e.cu_die_), line_ctx_(e.line_ctx_)
62         {
63             e.cu_die_ = nullptr;
64             e.line_ctx_ = nullptr;
65         }
66 
67         ~CompUnit();
68 
69         CompUnit &operator=(CompUnit &&e)
70         {
71             dbg_ = e.dbg_;
72             cu_die_ = e.cu_die_;
73             e.cu_die_ = nullptr;
74             line_ctx_ = e.line_ctx_;
75             e.line_ctx_ = nullptr;
76             return *this;
77         }
78 
GetDie()79         Dwarf_Die GetDie() const
80         {
81             return cu_die_;
82         }
83 
84         Dwarf_Line_Context GetLineContext();
85 
86         NO_COPY_SEMANTIC(CompUnit);
87 
88     private:
89         Dwarf_Debug dbg_;
90         Dwarf_Die cu_die_;
91         Dwarf_Line_Context line_ctx_ {nullptr};
92     };
93 
94     class Range {
95     public:
96         Range(Dwarf_Addr low_pc, Dwarf_Addr high_pc, CompUnit *cu = nullptr,
97               const std::string &function = std::string())  // NOLINT(modernize-pass-by-value)
low_pc_(low_pc)98             : low_pc_(low_pc), high_pc_(high_pc), cu_(cu), function_(function)
99         {
100         }
101 
GetLowPc()102         Dwarf_Addr GetLowPc() const
103         {
104             return low_pc_;
105         }
106 
GetHighPc()107         Dwarf_Addr GetHighPc() const
108         {
109             return high_pc_;
110         }
111 
Contain(Dwarf_Addr addr)112         bool Contain(Dwarf_Addr addr) const
113         {
114             return low_pc_ <= addr && addr < high_pc_;
115         }
116 
Contain(const Range & r)117         bool Contain(const Range &r) const
118         {
119             return low_pc_ <= r.low_pc_ && r.high_pc_ <= high_pc_;
120         }
121 
GetCu()122         CompUnit *GetCu() const
123         {
124             return cu_;
125         }
126 
GetFunction()127         std::string GetFunction() const
128         {
129             return function_;
130         }
131 
SetFunction(const std::string & function)132         void SetFunction(const std::string &function)
133         {
134             this->function_ = function;
135         }
136 
137         bool operator<(const Range &r) const
138         {
139             return high_pc_ < r.high_pc_;
140         }
141 
142         bool operator==(const Range &r) const
143         {
144             return low_pc_ == r.low_pc_ && high_pc_ == r.high_pc_;
145         }
146 
147     private:
148         Dwarf_Addr low_pc_;
149         Dwarf_Addr high_pc_;
150         CompUnit *cu_ = nullptr;
151         std::string function_;
152     };
153 
154 private:
155     bool FindCompUnitByPc(uintptr_t pc, Dwarf_Die *cu_die);
156     void TraverseChildren(CompUnit *cu, Dwarf_Die die);
157     void TraverseSiblings(CompUnit *cu, Dwarf_Die die);
158     void GetFunctionName(Dwarf_Die die, std::string *function);
159     void AddFunction(CompUnit *cu, Dwarf_Addr low_pc, Dwarf_Addr high_pc, const std::string &function);
160     bool GetSrcFileAndLine(uintptr_t pc, Dwarf_Line_Context line_ctx, std::string *src_file, uint32_t *line);
161     Dwarf_Line GetLastLineWithPc(Dwarf_Addr pc, Span<Dwarf_Line>::ConstIterator it,
162                                  Span<Dwarf_Line>::ConstIterator end);
163     void GetSrcFileAndLine(Dwarf_Line line, std::string *out_src_file, uint32_t *out_line);
164     bool PcMatches(uintptr_t pc, Dwarf_Die die);
165     bool GetDieRange(Dwarf_Die die, Dwarf_Addr *out_low_pc, Dwarf_Addr *out_high_pc);
166     bool GetDieRangeForPc(uintptr_t pc, Dwarf_Die die, Dwarf_Addr *out_low_pc, Dwarf_Addr *out_high_pc);
167     bool FindRangeForPc(uintptr_t pc, const Span<Dwarf_Ranges> &ranges, Dwarf_Addr base_addr, Dwarf_Addr *out_low_pc,
168                         Dwarf_Addr *out_high_pc);
169 
170 private:
171     static constexpr int INVALID_FD = -1;
172 
173     int fd_ {INVALID_FD};
174     Dwarf_Debug dbg_ {nullptr};
175     Dwarf_Arange *aranges_ {nullptr};
176     Dwarf_Signed arange_count_ {0};
177     std::list<CompUnit> cu_list_;
178     std::set<Range> ranges_;
179 };
180 
181 }  // namespace panda
182 #endif  // PANDA_DEBUG_INFO_H_
183