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_CFA_H 18 #define _LIBUNWINDSTACK_DWARF_CFA_H 19 20 #include <stdint.h> 21 22 #include <stack> 23 #include <string> 24 #include <type_traits> 25 #include <vector> 26 27 #include <unwindstack/DwarfError.h> 28 #include <unwindstack/DwarfLocation.h> 29 #include <unwindstack/DwarfMemory.h> 30 #include <unwindstack/DwarfStructs.h> 31 32 namespace unwindstack { 33 34 // DWARF Standard home: http://dwarfstd.org/ 35 // This code is based on DWARF 4: http://http://dwarfstd.org/doc/DWARF4.pdf 36 // See section 6.4.2.1 for a description of the DW_CFA_xxx values. 37 38 class DwarfCfaInfo { 39 public: 40 enum DisplayType : uint8_t { 41 DWARF_DISPLAY_NONE = 0, 42 DWARF_DISPLAY_REGISTER, 43 DWARF_DISPLAY_NUMBER, 44 DWARF_DISPLAY_SIGNED_NUMBER, 45 DWARF_DISPLAY_EVAL_BLOCK, 46 DWARF_DISPLAY_ADDRESS, 47 DWARF_DISPLAY_SET_LOC, 48 DWARF_DISPLAY_ADVANCE_LOC, 49 }; 50 51 struct Info { 52 const char* name; 53 uint8_t supported_version; 54 uint8_t num_operands; 55 uint8_t operands[2]; 56 uint8_t display_operands[2]; 57 }; 58 59 const static Info kTable[64]; 60 }; 61 62 template <typename AddressType> 63 class DwarfCfa { 64 // Signed version of AddressType 65 typedef typename std::make_signed<AddressType>::type SignedType; 66 67 public: DwarfCfa(DwarfMemory * memory,const DwarfFde * fde)68 DwarfCfa(DwarfMemory* memory, const DwarfFde* fde) : memory_(memory), fde_(fde) {} 69 virtual ~DwarfCfa() = default; 70 71 bool GetLocationInfo(uint64_t pc, uint64_t start_offset, uint64_t end_offset, 72 dwarf_loc_regs_t* loc_regs); 73 74 bool Log(uint32_t indent, uint64_t pc, uint64_t load_bias, uint64_t start_offset, 75 uint64_t end_offset); 76 last_error()77 const DwarfErrorData& last_error() { return last_error_; } LastErrorCode()78 DwarfErrorCode LastErrorCode() { return last_error_.code; } LastErrorAddress()79 uint64_t LastErrorAddress() { return last_error_.address; } 80 cur_pc()81 AddressType cur_pc() { return cur_pc_; } 82 set_cie_loc_regs(const dwarf_loc_regs_t * cie_loc_regs)83 void set_cie_loc_regs(const dwarf_loc_regs_t* cie_loc_regs) { cie_loc_regs_ = cie_loc_regs; } 84 85 protected: 86 std::string GetOperandString(uint8_t operand, uint64_t value, uint64_t* cur_pc); 87 88 bool LogOffsetRegisterString(uint32_t indent, uint64_t cfa_offset, uint8_t reg); 89 90 bool LogInstruction(uint32_t indent, uint64_t cfa_offset, uint8_t op, uint64_t* cur_pc); 91 92 private: 93 DwarfErrorData last_error_; 94 DwarfMemory* memory_; 95 const DwarfFde* fde_; 96 97 AddressType cur_pc_; 98 const dwarf_loc_regs_t* cie_loc_regs_ = nullptr; 99 std::vector<AddressType> operands_; 100 std::stack<dwarf_loc_regs_t> loc_reg_state_; 101 102 // CFA processing functions. 103 bool cfa_nop(dwarf_loc_regs_t*); 104 bool cfa_set_loc(dwarf_loc_regs_t*); 105 bool cfa_advance_loc(dwarf_loc_regs_t*); 106 bool cfa_offset(dwarf_loc_regs_t*); 107 bool cfa_restore(dwarf_loc_regs_t*); 108 bool cfa_undefined(dwarf_loc_regs_t*); 109 bool cfa_same_value(dwarf_loc_regs_t*); 110 bool cfa_register(dwarf_loc_regs_t*); 111 bool cfa_remember_state(dwarf_loc_regs_t*); 112 bool cfa_restore_state(dwarf_loc_regs_t*); 113 bool cfa_def_cfa(dwarf_loc_regs_t*); 114 bool cfa_def_cfa_register(dwarf_loc_regs_t*); 115 bool cfa_def_cfa_offset(dwarf_loc_regs_t*); 116 bool cfa_def_cfa_expression(dwarf_loc_regs_t*); 117 bool cfa_expression(dwarf_loc_regs_t*); 118 bool cfa_offset_extended_sf(dwarf_loc_regs_t*); 119 bool cfa_def_cfa_sf(dwarf_loc_regs_t*); 120 bool cfa_def_cfa_offset_sf(dwarf_loc_regs_t*); 121 bool cfa_val_offset(dwarf_loc_regs_t*); 122 bool cfa_val_offset_sf(dwarf_loc_regs_t*); 123 bool cfa_val_expression(dwarf_loc_regs_t*); 124 bool cfa_gnu_negative_offset_extended(dwarf_loc_regs_t*); 125 126 using process_func = bool (DwarfCfa::*)(dwarf_loc_regs_t*); 127 constexpr static process_func kCallbackTable[64] = { 128 // 0x00 DW_CFA_nop 129 &DwarfCfa::cfa_nop, 130 // 0x01 DW_CFA_set_loc 131 &DwarfCfa::cfa_set_loc, 132 // 0x02 DW_CFA_advance_loc1 133 &DwarfCfa::cfa_advance_loc, 134 // 0x03 DW_CFA_advance_loc2 135 &DwarfCfa::cfa_advance_loc, 136 // 0x04 DW_CFA_advance_loc4 137 &DwarfCfa::cfa_advance_loc, 138 // 0x05 DW_CFA_offset_extended 139 &DwarfCfa::cfa_offset, 140 // 0x06 DW_CFA_restore_extended 141 &DwarfCfa::cfa_restore, 142 // 0x07 DW_CFA_undefined 143 &DwarfCfa::cfa_undefined, 144 // 0x08 DW_CFA_same_value 145 &DwarfCfa::cfa_same_value, 146 // 0x09 DW_CFA_register 147 &DwarfCfa::cfa_register, 148 // 0x0a DW_CFA_remember_state 149 &DwarfCfa::cfa_remember_state, 150 // 0x0b DW_CFA_restore_state 151 &DwarfCfa::cfa_restore_state, 152 // 0x0c DW_CFA_def_cfa 153 &DwarfCfa::cfa_def_cfa, 154 // 0x0d DW_CFA_def_cfa_register 155 &DwarfCfa::cfa_def_cfa_register, 156 // 0x0e DW_CFA_def_cfa_offset 157 &DwarfCfa::cfa_def_cfa_offset, 158 // 0x0f DW_CFA_def_cfa_expression 159 &DwarfCfa::cfa_def_cfa_expression, 160 // 0x10 DW_CFA_expression 161 &DwarfCfa::cfa_expression, 162 // 0x11 DW_CFA_offset_extended_sf 163 &DwarfCfa::cfa_offset_extended_sf, 164 // 0x12 DW_CFA_def_cfa_sf 165 &DwarfCfa::cfa_def_cfa_sf, 166 // 0x13 DW_CFA_def_cfa_offset_sf 167 &DwarfCfa::cfa_def_cfa_offset_sf, 168 // 0x14 DW_CFA_val_offset 169 &DwarfCfa::cfa_val_offset, 170 // 0x15 DW_CFA_val_offset_sf 171 &DwarfCfa::cfa_val_offset_sf, 172 // 0x16 DW_CFA_val_expression 173 &DwarfCfa::cfa_val_expression, 174 // 0x17 illegal cfa 175 nullptr, 176 // 0x18 illegal cfa 177 nullptr, 178 // 0x19 illegal cfa 179 nullptr, 180 // 0x1a illegal cfa 181 nullptr, 182 // 0x1b illegal cfa 183 nullptr, 184 // 0x1c DW_CFA_lo_user (Treat this as illegal) 185 nullptr, 186 // 0x1d illegal cfa 187 nullptr, 188 // 0x1e illegal cfa 189 nullptr, 190 // 0x1f illegal cfa 191 nullptr, 192 // 0x20 illegal cfa 193 nullptr, 194 // 0x21 illegal cfa 195 nullptr, 196 // 0x22 illegal cfa 197 nullptr, 198 // 0x23 illegal cfa 199 nullptr, 200 // 0x24 illegal cfa 201 nullptr, 202 // 0x25 illegal cfa 203 nullptr, 204 // 0x26 illegal cfa 205 nullptr, 206 // 0x27 illegal cfa 207 nullptr, 208 // 0x28 illegal cfa 209 nullptr, 210 // 0x29 illegal cfa 211 nullptr, 212 // 0x2a illegal cfa 213 nullptr, 214 // 0x2b illegal cfa 215 nullptr, 216 // 0x2c illegal cfa 217 nullptr, 218 // 0x2d DW_CFA_GNU_window_save (Treat this as illegal) 219 nullptr, 220 // 0x2e DW_CFA_GNU_args_size 221 &DwarfCfa::cfa_nop, 222 // 0x2f DW_CFA_GNU_negative_offset_extended 223 &DwarfCfa::cfa_gnu_negative_offset_extended, 224 // 0x30 illegal cfa 225 nullptr, 226 // 0x31 illegal cfa 227 nullptr, 228 // 0x32 illegal cfa 229 nullptr, 230 // 0x33 illegal cfa 231 nullptr, 232 // 0x34 illegal cfa 233 nullptr, 234 // 0x35 illegal cfa 235 nullptr, 236 // 0x36 illegal cfa 237 nullptr, 238 // 0x37 illegal cfa 239 nullptr, 240 // 0x38 illegal cfa 241 nullptr, 242 // 0x39 illegal cfa 243 nullptr, 244 // 0x3a illegal cfa 245 nullptr, 246 // 0x3b illegal cfa 247 nullptr, 248 // 0x3c illegal cfa 249 nullptr, 250 // 0x3d illegal cfa 251 nullptr, 252 // 0x3e illegal cfa 253 nullptr, 254 // 0x3f DW_CFA_hi_user (Treat this as illegal) 255 nullptr, 256 }; 257 }; 258 259 } // namespace unwindstack 260 261 #endif // _LIBUNWINDSTACK_DWARF_CFA_H 262