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