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