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 enum ArchEnum : uint8_t;
35 class Memory;
36 class Regs;
37 template <typename AddressType>
38 struct RegsInfo;
39 
40 class DwarfSection {
41  public:
42   DwarfSection(Memory* memory);
43   virtual ~DwarfSection() = default;
44 
45   class iterator : public std::iterator<std::bidirectional_iterator_tag, DwarfFde*> {
46    public:
iterator(DwarfSection * section,size_t index)47     iterator(DwarfSection* section, size_t index) : index_(index) {
48       section->GetFdes(&fdes_);
49       if (index_ == static_cast<size_t>(-1)) {
50         index_ = fdes_.size();
51       }
52     }
53 
54     iterator& operator++() {
55       index_++;
56       return *this;
57     }
58     iterator& operator++(int increment) {
59       index_ += increment;
60       return *this;
61     }
62     iterator& operator--() {
63       index_--;
64       return *this;
65     }
66     iterator& operator--(int decrement) {
67       index_ -= decrement;
68       return *this;
69     }
70 
71     bool operator==(const iterator& rhs) { return this->index_ == rhs.index_; }
72     bool operator!=(const iterator& rhs) { return this->index_ != rhs.index_; }
73 
74     const DwarfFde* operator*() {
75       if (index_ > fdes_.size()) return nullptr;
76       return fdes_[index_];
77     }
78 
79    private:
80     std::vector<const DwarfFde*> fdes_;
81     size_t index_ = 0;
82   };
83 
begin()84   iterator begin() { return iterator(this, 0); }
end()85   iterator end() { return iterator(this, static_cast<size_t>(-1)); }
86 
LastErrorCode()87   DwarfErrorCode LastErrorCode() { return last_error_.code; }
LastErrorAddress()88   uint64_t LastErrorAddress() { return last_error_.address; }
89 
90   virtual bool Init(uint64_t offset, uint64_t size, int64_t section_bias) = 0;
91 
92   virtual bool Eval(const DwarfCie*, Memory*, const dwarf_loc_regs_t&, Regs*, bool*) = 0;
93 
94   virtual bool Log(uint8_t indent, uint64_t pc, const DwarfFde* fde, ArchEnum arch) = 0;
95 
96   virtual void GetFdes(std::vector<const DwarfFde*>* fdes) = 0;
97 
98   virtual const DwarfFde* GetFdeFromPc(uint64_t pc) = 0;
99 
100   virtual bool GetCfaLocationInfo(uint64_t pc, const DwarfFde* fde, dwarf_loc_regs_t* loc_regs,
101                                   ArchEnum arch) = 0;
102 
103   virtual uint64_t GetCieOffsetFromFde32(uint32_t pointer) = 0;
104 
105   virtual uint64_t GetCieOffsetFromFde64(uint64_t pointer) = 0;
106 
107   virtual uint64_t AdjustPcFromFde(uint64_t pc) = 0;
108 
109   bool Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished);
110 
111  protected:
112   DwarfMemory memory_;
113   DwarfErrorData last_error_{DWARF_ERROR_NONE, 0};
114 
115   uint32_t cie32_value_ = 0;
116   uint64_t cie64_value_ = 0;
117 
118   std::unordered_map<uint64_t, DwarfFde> fde_entries_;
119   std::unordered_map<uint64_t, DwarfCie> cie_entries_;
120   std::unordered_map<uint64_t, dwarf_loc_regs_t> cie_loc_regs_;
121   std::map<uint64_t, dwarf_loc_regs_t> loc_regs_;  // Single row indexed by pc_end.
122 };
123 
124 template <typename AddressType>
125 class DwarfSectionImpl : public DwarfSection {
126  public:
DwarfSectionImpl(Memory * memory)127   DwarfSectionImpl(Memory* memory) : DwarfSection(memory) {}
128   virtual ~DwarfSectionImpl() = default;
129 
130   bool Init(uint64_t offset, uint64_t size, int64_t section_bias) override;
131 
132   const DwarfCie* GetCieFromOffset(uint64_t offset);
133 
134   const DwarfFde* GetFdeFromOffset(uint64_t offset);
135 
136   const DwarfFde* GetFdeFromPc(uint64_t pc) override;
137 
138   void GetFdes(std::vector<const DwarfFde*>* fdes) override;
139 
140   bool EvalRegister(const DwarfLocation* loc, uint32_t reg, AddressType* reg_ptr, void* info);
141 
142   bool Eval(const DwarfCie* cie, Memory* regular_memory, const dwarf_loc_regs_t& loc_regs,
143             Regs* regs, bool* finished) override;
144 
145   bool GetCfaLocationInfo(uint64_t pc, const DwarfFde* fde, dwarf_loc_regs_t* loc_regs,
146                           ArchEnum arch) override;
147 
148   bool Log(uint8_t indent, uint64_t pc, const DwarfFde* fde, ArchEnum arch) override;
149 
150  protected:
151   bool GetNextCieOrFde(const DwarfFde** fde_entry);
152 
153   bool FillInCieHeader(DwarfCie* cie);
154 
155   bool FillInCie(DwarfCie* cie);
156 
157   bool FillInFdeHeader(DwarfFde* fde);
158 
159   bool FillInFde(DwarfFde* fde);
160 
161   bool EvalExpression(const DwarfLocation& loc, Memory* regular_memory, AddressType* value,
162                       RegsInfo<AddressType>* regs_info, bool* is_dex_pc);
163 
164   void InsertFde(const DwarfFde* fde);
165 
166   int64_t section_bias_ = 0;
167   uint64_t entries_offset_ = 0;
168   uint64_t entries_end_ = 0;
169   uint64_t next_entries_offset_ = 0;
170   uint64_t pc_offset_ = 0;
171 
172   std::map<uint64_t, std::pair<uint64_t, const DwarfFde*>> fdes_;
173 };
174 
175 }  // namespace unwindstack
176 
177 #endif  // _LIBUNWINDSTACK_DWARF_SECTION_H
178