blob: 62b9b7ac078973caab2efd60edc8fd8a83bf9b38 [file] [log] [blame]
Christopher Ferris8642fcb2017-04-24 11:14:39 -07001/*
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
Christopher Ferrisd226a512017-07-14 10:37:19 -070027#include <unwindstack/DwarfLocation.h>
28#include <unwindstack/DwarfMemory.h>
29#include <unwindstack/DwarfStructs.h>
30
Christopher Ferris8642fcb2017-04-24 11:14:39 -070031#include "DwarfError.h"
Christopher Ferrisd226a512017-07-14 10:37:19 -070032
33namespace unwindstack {
Christopher Ferris8642fcb2017-04-24 11:14:39 -070034
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
39class 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
63template <typename AddressType>
64class DwarfCfa {
65 // Signed version of AddressType
66 typedef typename std::make_signed<AddressType>::type SignedType;
67
68 public:
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070069 DwarfCfa(DwarfMemory* memory, const DwarfFde* fde) : memory_(memory), fde_(fde) {}
Christopher Ferris8642fcb2017-04-24 11:14:39 -070070 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_;
Christopher Ferris53a3c9b2017-05-10 18:34:15 -070094 const DwarfFde* fde_;
Christopher Ferris8642fcb2017-04-24 11:14:39 -070095
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
Christopher Ferrisd226a512017-07-14 10:37:19 -0700258} // namespace unwindstack
259
Christopher Ferris8642fcb2017-04-24 11:14:39 -0700260#endif // _LIBUNWINDSTACK_DWARF_CFA_H