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 #pragma once 18 19 #include <stddef.h> 20 #include <stdint.h> 21 22 #include <iterator> 23 #include <map> 24 #include <memory> 25 #include <optional> 26 #include <unordered_map> 27 #include <utility> 28 #include <vector> 29 30 #include <unwindstack/DwarfError.h> 31 #include <unwindstack/DwarfLocation.h> 32 #include <unwindstack/DwarfMemory.h> 33 #include <unwindstack/DwarfStructs.h> 34 35 namespace unwindstack { 36 37 // Forward declarations. 38 enum ArchEnum : uint8_t; 39 class Memory; 40 class Regs; 41 template <typename AddressType> 42 struct RegsInfo; 43 struct SectionInfo; 44 45 class DwarfSection { 46 public: 47 DwarfSection(std::shared_ptr<Memory>& memory); 48 virtual ~DwarfSection() = default; 49 50 class iterator { 51 public: 52 using iterator_category = std::bidirectional_iterator_tag; 53 using value_type = DwarfFde*; 54 using difference_type = ptrdiff_t; 55 using pointer = DwarfFde**; 56 using reference = DwarfFde*&; 57 iterator(DwarfSection * section,size_t index)58 iterator(DwarfSection* section, size_t index) : index_(index) { 59 section->GetFdes(&fdes_); 60 if (index_ == static_cast<size_t>(-1)) { 61 index_ = fdes_.size(); 62 } 63 } 64 65 iterator& operator++() { 66 index_++; 67 return *this; 68 } 69 iterator& operator++(int increment) { 70 index_ += increment; 71 return *this; 72 } 73 iterator& operator--() { 74 index_--; 75 return *this; 76 } 77 iterator& operator--(int decrement) { 78 index_ -= decrement; 79 return *this; 80 } 81 82 bool operator==(const iterator& rhs) const { return this->index_ == rhs.index_; } 83 bool operator!=(const iterator& rhs) const { return this->index_ != rhs.index_; } 84 85 const DwarfFde* operator*() { 86 if (index_ > fdes_.size()) return nullptr; 87 return fdes_[index_]; 88 } 89 90 private: 91 std::vector<const DwarfFde*> fdes_; 92 size_t index_ = 0; 93 }; 94 begin()95 iterator begin() { return iterator(this, 0); } end()96 iterator end() { return iterator(this, static_cast<size_t>(-1)); } 97 LastErrorCode()98 DwarfErrorCode LastErrorCode() { return last_error_.code; } LastErrorAddress()99 uint64_t LastErrorAddress() { return last_error_.address; } 100 101 virtual bool Init(const SectionInfo& info) = 0; 102 103 virtual bool Eval(const DwarfCie*, Memory*, const DwarfLocations&, Regs*, bool*) = 0; 104 105 virtual bool Log(uint8_t indent, uint64_t pc, const DwarfFde* fde, ArchEnum arch) = 0; 106 107 virtual void GetFdes(std::vector<const DwarfFde*>* fdes) = 0; 108 109 virtual const DwarfFde* GetFdeFromPc(uint64_t pc) = 0; 110 111 virtual bool GetCfaLocationInfo(uint64_t pc, const DwarfFde* fde, DwarfLocations* loc_regs, 112 ArchEnum arch) = 0; 113 114 virtual uint64_t GetCieOffsetFromFde32(uint32_t pointer) = 0; 115 116 virtual uint64_t GetCieOffsetFromFde64(uint64_t pointer) = 0; 117 118 virtual uint64_t AdjustPcFromFde(uint64_t pc) = 0; 119 120 bool Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished, bool* is_signal_frame); 121 122 protected: 123 DwarfMemory memory_; 124 DwarfErrorData last_error_{DWARF_ERROR_NONE, 0}; 125 126 uint32_t cie32_value_ = 0; 127 uint64_t cie64_value_ = 0; 128 129 std::unordered_map<uint64_t, DwarfFde> fde_entries_; 130 std::unordered_map<uint64_t, DwarfCie> cie_entries_; 131 std::unordered_map<uint64_t, DwarfLocations> cie_loc_regs_; 132 std::map<uint64_t, DwarfLocations> loc_regs_; // Single row indexed by pc_end. 133 }; 134 135 template <typename AddressType> 136 class DwarfSectionImpl : public DwarfSection { 137 public: DwarfSectionImpl(std::shared_ptr<Memory> & memory)138 DwarfSectionImpl(std::shared_ptr<Memory>& memory) : DwarfSection(memory) {} 139 virtual ~DwarfSectionImpl() = default; 140 141 bool Init(const SectionInfo& info) override; 142 143 const DwarfCie* GetCieFromOffset(uint64_t offset); 144 145 const DwarfFde* GetFdeFromOffset(uint64_t offset); 146 147 const DwarfFde* GetFdeFromPc(uint64_t pc) override; 148 149 void GetFdes(std::vector<const DwarfFde*>* fdes) override; 150 151 bool EvalRegister(const DwarfLocation* loc, uint32_t reg, AddressType* reg_ptr, void* info); 152 153 bool Eval(const DwarfCie* cie, Memory* regular_memory, const DwarfLocations& loc_regs, Regs* regs, 154 bool* finished) override; 155 156 bool GetCfaLocationInfo(uint64_t pc, const DwarfFde* fde, DwarfLocations* loc_regs, 157 ArchEnum arch) override; 158 159 bool Log(uint8_t indent, uint64_t pc, const DwarfFde* fde, ArchEnum arch) override; 160 161 protected: 162 using DwarfFdeMap = 163 std::map</*end*/ uint64_t, std::pair</*start*/ uint64_t, /*offset*/ uint64_t>>; 164 165 bool GetNextCieOrFde(/*inout*/ uint64_t& offset, /*out*/ std::optional<DwarfFde>& fde); 166 167 bool FillInCieHeader(DwarfCie* cie); 168 169 bool FillInCie(DwarfCie* cie); 170 171 bool FillInFdeHeader(DwarfFde* fde); 172 173 bool FillInFde(DwarfFde* fde); 174 175 bool EvalExpression(const DwarfLocation& loc, Memory* regular_memory, AddressType* value, 176 RegsInfo<AddressType>* regs_info, bool* is_dex_pc); 177 178 static void InsertFde(uint64_t fde_offset, const DwarfFde* fde, /*out*/ DwarfFdeMap& fdes); 179 180 void BuildFdeIndex(); 181 182 int64_t section_bias_ = 0; 183 uint64_t entries_offset_ = 0; 184 uint64_t entries_end_ = 0; 185 uint64_t pc_offset_ = 0; 186 187 // Binary search table (similar to .eh_frame_hdr). Contains only FDE offsets to save memory. 188 std::vector<std::pair</*function end address*/ uint64_t, /*FDE offset*/ uint64_t>> fde_index_; 189 }; 190 191 } // namespace unwindstack 192