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