• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef _LIBUNWINDSTACK_DWARF_SECTION_H
18 #define _LIBUNWINDSTACK_DWARF_SECTION_H
19 
20 #include <stdint.h>
21 
22 #include <iterator>
23 #include <map>
24 #include <unordered_map>
25 
26 #include <unwindstack/DwarfError.h>
27 #include <unwindstack/DwarfLocation.h>
28 #include <unwindstack/DwarfMemory.h>
29 #include <unwindstack/DwarfStructs.h>
30 
31 namespace unwindstack {
32 
33 // Forward declarations.
34 class Memory;
35 class Regs;
36 template <typename AddressType>
37 struct RegsInfo;
38 
39 class DwarfSection {
40  public:
41   DwarfSection(Memory* memory);
42   virtual ~DwarfSection() = default;
43 
44   class iterator : public std::iterator<std::bidirectional_iterator_tag, DwarfFde*> {
45    public:
iterator(DwarfSection * section,size_t index)46     iterator(DwarfSection* section, size_t index) : index_(index) {
47       section->GetFdes(&fdes_);
48       if (index_ == static_cast<size_t>(-1)) {
49         index_ = fdes_.size();
50       }
51     }
52 
53     iterator& operator++() {
54       index_++;
55       return *this;
56     }
57     iterator& operator++(int increment) {
58       index_ += increment;
59       return *this;
60     }
61     iterator& operator--() {
62       index_--;
63       return *this;
64     }
65     iterator& operator--(int decrement) {
66       index_ -= decrement;
67       return *this;
68     }
69 
70     bool operator==(const iterator& rhs) { return this->index_ == rhs.index_; }
71     bool operator!=(const iterator& rhs) { return this->index_ != rhs.index_; }
72 
73     const DwarfFde* operator*() {
74       if (index_ > fdes_.size()) return nullptr;
75       return fdes_[index_];
76     }
77 
78    private:
79     std::vector<const DwarfFde*> fdes_;
80     size_t index_ = 0;
81   };
82 
begin()83   iterator begin() { return iterator(this, 0); }
end()84   iterator end() { return iterator(this, static_cast<size_t>(-1)); }
85 
LastErrorCode()86   DwarfErrorCode LastErrorCode() { return last_error_.code; }
LastErrorAddress()87   uint64_t LastErrorAddress() { return last_error_.address; }
88 
89   virtual bool Init(uint64_t offset, uint64_t size, uint64_t load_bias) = 0;
90 
91   virtual bool Eval(const DwarfCie*, Memory*, const dwarf_loc_regs_t&, Regs*, bool*) = 0;
92 
93   virtual bool Log(uint8_t indent, uint64_t pc, const DwarfFde* fde) = 0;
94 
95   virtual void GetFdes(std::vector<const DwarfFde*>* fdes) = 0;
96 
97   virtual const DwarfFde* GetFdeFromPc(uint64_t pc) = 0;
98 
99   virtual bool GetCfaLocationInfo(uint64_t pc, const DwarfFde* fde, dwarf_loc_regs_t* loc_regs) = 0;
100 
101   virtual uint64_t GetCieOffsetFromFde32(uint32_t pointer) = 0;
102 
103   virtual uint64_t GetCieOffsetFromFde64(uint64_t pointer) = 0;
104 
105   virtual uint64_t AdjustPcFromFde(uint64_t pc) = 0;
106 
107   bool Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished);
108 
109  protected:
110   DwarfMemory memory_;
111   DwarfErrorData last_error_{DWARF_ERROR_NONE, 0};
112 
113   uint32_t cie32_value_ = 0;
114   uint64_t cie64_value_ = 0;
115 
116   std::unordered_map<uint64_t, DwarfFde> fde_entries_;
117   std::unordered_map<uint64_t, DwarfCie> cie_entries_;
118   std::unordered_map<uint64_t, dwarf_loc_regs_t> cie_loc_regs_;
119   std::map<uint64_t, dwarf_loc_regs_t> loc_regs_;  // Single row indexed by pc_end.
120 };
121 
122 template <typename AddressType>
123 class DwarfSectionImpl : public DwarfSection {
124  public:
DwarfSectionImpl(Memory * memory)125   DwarfSectionImpl(Memory* memory) : DwarfSection(memory) {}
126   virtual ~DwarfSectionImpl() = default;
127 
128   const DwarfCie* GetCieFromOffset(uint64_t offset);
129 
130   const DwarfFde* GetFdeFromOffset(uint64_t offset);
131 
132   bool EvalRegister(const DwarfLocation* loc, uint32_t reg, AddressType* reg_ptr, void* info);
133 
134   bool Eval(const DwarfCie* cie, Memory* regular_memory, const dwarf_loc_regs_t& loc_regs,
135             Regs* regs, bool* finished) override;
136 
137   bool GetCfaLocationInfo(uint64_t pc, const DwarfFde* fde, dwarf_loc_regs_t* loc_regs) override;
138 
139   bool Log(uint8_t indent, uint64_t pc, const DwarfFde* fde) override;
140 
141  protected:
142   bool FillInCieHeader(DwarfCie* cie);
143 
144   bool FillInCie(DwarfCie* cie);
145 
146   bool FillInFdeHeader(DwarfFde* fde);
147 
148   bool FillInFde(DwarfFde* fde);
149 
150   bool EvalExpression(const DwarfLocation& loc, Memory* regular_memory, AddressType* value,
151                       RegsInfo<AddressType>* regs_info, bool* is_dex_pc);
152 
153   uint64_t load_bias_ = 0;
154   uint64_t entries_offset_ = 0;
155   uint64_t entries_end_ = 0;
156   uint64_t pc_offset_ = 0;
157 };
158 
159 template <typename AddressType>
160 class DwarfSectionImplNoHdr : public DwarfSectionImpl<AddressType> {
161  public:
162   // Add these so that the protected members of DwarfSectionImpl
163   // can be accessed without needing a this->.
164   using DwarfSectionImpl<AddressType>::memory_;
165   using DwarfSectionImpl<AddressType>::pc_offset_;
166   using DwarfSectionImpl<AddressType>::entries_offset_;
167   using DwarfSectionImpl<AddressType>::entries_end_;
168   using DwarfSectionImpl<AddressType>::last_error_;
169   using DwarfSectionImpl<AddressType>::load_bias_;
170   using DwarfSectionImpl<AddressType>::cie_entries_;
171   using DwarfSectionImpl<AddressType>::fde_entries_;
172   using DwarfSectionImpl<AddressType>::cie32_value_;
173   using DwarfSectionImpl<AddressType>::cie64_value_;
174 
DwarfSectionImplNoHdr(Memory * memory)175   DwarfSectionImplNoHdr(Memory* memory) : DwarfSectionImpl<AddressType>(memory) {}
176   virtual ~DwarfSectionImplNoHdr() = default;
177 
178   bool Init(uint64_t offset, uint64_t size, uint64_t load_bias) override;
179 
180   const DwarfFde* GetFdeFromPc(uint64_t pc) override;
181 
182   void GetFdes(std::vector<const DwarfFde*>* fdes) override;
183 
184  protected:
185   bool GetNextCieOrFde(DwarfFde** fde_entry);
186 
187   void InsertFde(const DwarfFde* fde);
188 
189   uint64_t next_entries_offset_ = 0;
190 
191   std::map<uint64_t, std::pair<uint64_t, const DwarfFde*>> fdes_;
192 };
193 
194 }  // namespace unwindstack
195 
196 #endif  // _LIBUNWINDSTACK_DWARF_SECTION_H
197