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