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) : section_(section), index_(index) {}
47 
48     iterator& operator++() {
49       index_++;
50       return *this;
51     }
52     iterator& operator++(int increment) {
53       index_ += increment;
54       return *this;
55     }
56     iterator& operator--() {
57       index_--;
58       return *this;
59     }
60     iterator& operator--(int decrement) {
61       index_ -= decrement;
62       return *this;
63     }
64 
65     bool operator==(const iterator& rhs) { return this->index_ == rhs.index_; }
66     bool operator!=(const iterator& rhs) { return this->index_ != rhs.index_; }
67 
68     const DwarfFde* operator*() { return section_->GetFdeFromIndex(index_); }
69 
70    private:
71     DwarfSection* section_ = nullptr;
72     size_t index_ = 0;
73   };
74 
begin()75   iterator begin() { return iterator(this, 0); }
end()76   iterator end() { return iterator(this, fde_count_); }
77 
LastErrorCode()78   DwarfErrorCode LastErrorCode() { return last_error_.code; }
LastErrorAddress()79   uint64_t LastErrorAddress() { return last_error_.address; }
80 
81   virtual bool Init(uint64_t offset, uint64_t size) = 0;
82 
83   virtual bool Eval(const DwarfCie*, Memory*, const dwarf_loc_regs_t&, Regs*, bool*) = 0;
84 
85   virtual bool GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_offset) = 0;
86 
87   virtual bool Log(uint8_t indent, uint64_t pc, uint64_t load_bias, const DwarfFde* fde) = 0;
88 
89   virtual const DwarfFde* GetFdeFromIndex(size_t index) = 0;
90 
91   const DwarfFde* GetFdeFromPc(uint64_t pc);
92 
93   virtual const DwarfFde* GetFdeFromOffset(uint64_t fde_offset) = 0;
94 
95   virtual bool GetCfaLocationInfo(uint64_t pc, const DwarfFde* fde, dwarf_loc_regs_t* loc_regs) = 0;
96 
97   virtual uint64_t GetCieOffsetFromFde32(uint32_t pointer) = 0;
98 
99   virtual uint64_t GetCieOffsetFromFde64(uint64_t pointer) = 0;
100 
101   virtual uint64_t AdjustPcFromFde(uint64_t pc) = 0;
102 
103   bool Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished);
104 
105  protected:
106   DwarfMemory memory_;
107   DwarfErrorData last_error_{DWARF_ERROR_NONE, 0};
108 
109   uint32_t cie32_value_ = 0;
110   uint64_t cie64_value_ = 0;
111 
112   uint64_t fde_count_ = 0;
113   std::unordered_map<uint64_t, DwarfFde> fde_entries_;
114   std::unordered_map<uint64_t, DwarfCie> cie_entries_;
115   std::unordered_map<uint64_t, dwarf_loc_regs_t> cie_loc_regs_;
116   std::map<uint64_t, dwarf_loc_regs_t> loc_regs_;  // Single row indexed by pc_end.
117 };
118 
119 template <typename AddressType>
120 class DwarfSectionImpl : public DwarfSection {
121  public:
122   struct FdeInfo {
FdeInfoFdeInfo123     FdeInfo(uint64_t offset, uint64_t start, uint64_t length)
124         : offset(offset), start(start), end(start + length) {}
125 
126     uint64_t offset;
127     AddressType start;
128     AddressType end;
129   };
130 
DwarfSectionImpl(Memory * memory)131   DwarfSectionImpl(Memory* memory) : DwarfSection(memory) {}
132   virtual ~DwarfSectionImpl() = default;
133 
134   bool Init(uint64_t offset, uint64_t size) override;
135 
136   bool GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_offset) override;
137 
138   const DwarfFde* GetFdeFromIndex(size_t index) 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   const DwarfCie* GetCie(uint64_t offset);
146   bool FillInCie(DwarfCie* cie);
147 
148   const DwarfFde* GetFdeFromOffset(uint64_t offset) override;
149   bool FillInFde(DwarfFde* fde);
150 
151   bool GetCfaLocationInfo(uint64_t pc, const DwarfFde* fde, dwarf_loc_regs_t* loc_regs) override;
152 
153   bool Log(uint8_t indent, uint64_t pc, uint64_t load_bias, const DwarfFde* fde) override;
154 
155  protected:
156   bool EvalExpression(const DwarfLocation& loc, Memory* regular_memory, AddressType* value,
157                       RegsInfo<AddressType>* regs_info, bool* is_dex_pc);
158 
159   bool GetCieInfo(uint8_t* segment_size, uint8_t* encoding);
160 
161   bool AddFdeInfo(uint64_t entry_offset, uint8_t segment_size, uint8_t encoding);
162 
163   bool CreateSortedFdeList();
164 
165   std::vector<FdeInfo> fdes_;
166   uint64_t entries_offset_;
167   uint64_t entries_end_;
168 };
169 
170 }  // namespace unwindstack
171 
172 #endif  // _LIBUNWINDSTACK_DWARF_SECTION_H
173