blob: d229e880d97dfb42d8a3c0942fec87e6f53171a2 [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- DWARFCallFrameInfo.cpp ----------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Chris Lattner30fdc8d2010-06-08 16:52:24 +000010// C Includes
11// C++ Includes
12#include <list>
13
Chris Lattner30fdc8d2010-06-08 16:52:24 +000014#include "lldb/Core/ArchSpec.h"
15#include "lldb/Core/Module.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000016#include "lldb/Core/Section.h"
Jason Molenda74303822013-03-20 21:57:42 +000017#include "lldb/Core/Timer.h"
Zachary Turner29cb8682017-03-03 20:57:05 +000018#include "lldb/Core/dwarf.h"
Greg Claytone38a5ed2012-01-05 03:57:59 +000019#include "lldb/Host/Host.h"
20#include "lldb/Symbol/DWARFCallFrameInfo.h"
21#include "lldb/Symbol/ObjectFile.h"
Jason Molendafbcb7f22010-09-10 07:49:16 +000022#include "lldb/Symbol/UnwindPlan.h"
Greg Claytone38a5ed2012-01-05 03:57:59 +000023#include "lldb/Target/RegisterContext.h"
24#include "lldb/Target/Thread.h"
Zachary Turner6f9e6902017-03-03 20:56:28 +000025#include "lldb/Utility/Log.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000026
27using namespace lldb;
28using namespace lldb_private;
29
Zachary Turner29cb8682017-03-03 20:57:05 +000030//----------------------------------------------------------------------
31// GetDwarfEHPtr
32//
33// Used for calls when the value type is specified by a DWARF EH Frame
34// pointer encoding.
35//----------------------------------------------------------------------
36static uint64_t
37GetGNUEHPointer(const DataExtractor &DE, offset_t *offset_ptr,
38 uint32_t eh_ptr_enc, addr_t pc_rel_addr, addr_t text_addr,
39 addr_t data_addr) //, BSDRelocs *data_relocs) const
40{
41 if (eh_ptr_enc == DW_EH_PE_omit)
42 return ULLONG_MAX; // Value isn't in the buffer...
43
44 uint64_t baseAddress = 0;
45 uint64_t addressValue = 0;
46 const uint32_t addr_size = DE.GetAddressByteSize();
47#ifdef LLDB_CONFIGURATION_DEBUG
48 assert(addr_size == 4 || addr_size == 8);
49#endif
50
51 bool signExtendValue = false;
52 // Decode the base part or adjust our offset
53 switch (eh_ptr_enc & 0x70) {
54 case DW_EH_PE_pcrel:
55 signExtendValue = true;
56 baseAddress = *offset_ptr;
57 if (pc_rel_addr != LLDB_INVALID_ADDRESS)
58 baseAddress += pc_rel_addr;
59 // else
60 // Log::GlobalWarning ("PC relative pointer encoding found with
61 // invalid pc relative address.");
62 break;
63
64 case DW_EH_PE_textrel:
65 signExtendValue = true;
66 if (text_addr != LLDB_INVALID_ADDRESS)
67 baseAddress = text_addr;
68 // else
69 // Log::GlobalWarning ("text relative pointer encoding being
70 // decoded with invalid text section address, setting base address
71 // to zero.");
72 break;
73
74 case DW_EH_PE_datarel:
75 signExtendValue = true;
76 if (data_addr != LLDB_INVALID_ADDRESS)
77 baseAddress = data_addr;
78 // else
79 // Log::GlobalWarning ("data relative pointer encoding being
80 // decoded with invalid data section address, setting base address
81 // to zero.");
82 break;
83
84 case DW_EH_PE_funcrel:
85 signExtendValue = true;
86 break;
87
88 case DW_EH_PE_aligned: {
89 // SetPointerSize should be called prior to extracting these so the
90 // pointer size is cached
91 assert(addr_size != 0);
92 if (addr_size) {
93 // Align to a address size boundary first
94 uint32_t alignOffset = *offset_ptr % addr_size;
95 if (alignOffset)
96 offset_ptr += addr_size - alignOffset;
97 }
98 } break;
99
100 default:
101 break;
102 }
103
104 // Decode the value part
105 switch (eh_ptr_enc & DW_EH_PE_MASK_ENCODING) {
106 case DW_EH_PE_absptr: {
107 addressValue = DE.GetAddress(offset_ptr);
108 // if (data_relocs)
109 // addressValue = data_relocs->Relocate(*offset_ptr -
110 // addr_size, *this, addressValue);
111 } break;
112 case DW_EH_PE_uleb128:
113 addressValue = DE.GetULEB128(offset_ptr);
114 break;
115 case DW_EH_PE_udata2:
116 addressValue = DE.GetU16(offset_ptr);
117 break;
118 case DW_EH_PE_udata4:
119 addressValue = DE.GetU32(offset_ptr);
120 break;
121 case DW_EH_PE_udata8:
122 addressValue = DE.GetU64(offset_ptr);
123 break;
124 case DW_EH_PE_sleb128:
125 addressValue = DE.GetSLEB128(offset_ptr);
126 break;
127 case DW_EH_PE_sdata2:
128 addressValue = (int16_t)DE.GetU16(offset_ptr);
129 break;
130 case DW_EH_PE_sdata4:
131 addressValue = (int32_t)DE.GetU32(offset_ptr);
132 break;
133 case DW_EH_PE_sdata8:
134 addressValue = (int64_t)DE.GetU64(offset_ptr);
135 break;
136 default:
137 // Unhandled encoding type
138 assert(eh_ptr_enc);
139 break;
140 }
141
142 // Since we promote everything to 64 bit, we may need to sign extend
143 if (signExtendValue && addr_size < sizeof(baseAddress)) {
144 uint64_t sign_bit = 1ull << ((addr_size * 8ull) - 1ull);
145 if (sign_bit & addressValue) {
146 uint64_t mask = ~sign_bit + 1;
147 addressValue |= mask;
148 }
149 }
150 return baseAddress + addressValue;
151}
152
Kate Stoneb9c1b512016-09-06 20:57:50 +0000153DWARFCallFrameInfo::DWARFCallFrameInfo(ObjectFile &objfile,
154 SectionSP &section_sp,
155 lldb::RegisterKind reg_kind,
156 bool is_eh_frame)
157 : m_objfile(objfile), m_section_sp(section_sp),
158 m_reg_kind(reg_kind), // The flavor of registers that the CFI data uses
159 // (enum RegisterKind)
160 m_flags(), m_cie_map(), m_cfi_data(), m_cfi_data_initialized(false),
161 m_fde_index(), m_fde_index_initialized(false),
162 m_is_eh_frame(is_eh_frame) {}
163
164DWARFCallFrameInfo::~DWARFCallFrameInfo() {}
165
166bool DWARFCallFrameInfo::GetUnwindPlan(Address addr, UnwindPlan &unwind_plan) {
167 FDEEntryMap::Entry fde_entry;
168
169 // Make sure that the Address we're searching for is the same object file
170 // as this DWARFCallFrameInfo, we only store File offsets in m_fde_index.
171 ModuleSP module_sp = addr.GetModule();
172 if (module_sp.get() == nullptr || module_sp->GetObjectFile() == nullptr ||
173 module_sp->GetObjectFile() != &m_objfile)
174 return false;
175
176 if (GetFDEEntryByFileAddress(addr.GetFileAddress(), fde_entry) == false)
177 return false;
178 return FDEToUnwindPlan(fde_entry.data, addr, unwind_plan);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000179}
180
Kate Stoneb9c1b512016-09-06 20:57:50 +0000181bool DWARFCallFrameInfo::GetAddressRange(Address addr, AddressRange &range) {
182
183 // Make sure that the Address we're searching for is the same object file
184 // as this DWARFCallFrameInfo, we only store File offsets in m_fde_index.
185 ModuleSP module_sp = addr.GetModule();
186 if (module_sp.get() == nullptr || module_sp->GetObjectFile() == nullptr ||
187 module_sp->GetObjectFile() != &m_objfile)
188 return false;
189
190 if (m_section_sp.get() == nullptr || m_section_sp->IsEncrypted())
191 return false;
192 GetFDEIndex();
193 FDEEntryMap::Entry *fde_entry =
194 m_fde_index.FindEntryThatContains(addr.GetFileAddress());
195 if (!fde_entry)
196 return false;
197
198 range = AddressRange(fde_entry->base, fde_entry->size,
199 m_objfile.GetSectionList());
200 return true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000201}
202
Kate Stoneb9c1b512016-09-06 20:57:50 +0000203bool DWARFCallFrameInfo::GetFDEEntryByFileAddress(
204 addr_t file_addr, FDEEntryMap::Entry &fde_entry) {
205 if (m_section_sp.get() == nullptr || m_section_sp->IsEncrypted())
206 return false;
Jason Molendafbcb7f22010-09-10 07:49:16 +0000207
Kate Stoneb9c1b512016-09-06 20:57:50 +0000208 GetFDEIndex();
Jason Molenda74303822013-03-20 21:57:42 +0000209
Kate Stoneb9c1b512016-09-06 20:57:50 +0000210 if (m_fde_index.IsEmpty())
211 return false;
Jason Molenda74303822013-03-20 21:57:42 +0000212
Kate Stoneb9c1b512016-09-06 20:57:50 +0000213 FDEEntryMap::Entry *fde = m_fde_index.FindEntryThatContains(file_addr);
214
215 if (fde == nullptr)
216 return false;
217
218 fde_entry = *fde;
219 return true;
Jason Molenda74303822013-03-20 21:57:42 +0000220}
221
Kate Stoneb9c1b512016-09-06 20:57:50 +0000222void DWARFCallFrameInfo::GetFunctionAddressAndSizeVector(
223 FunctionAddressAndSizeVector &function_info) {
224 GetFDEIndex();
225 const size_t count = m_fde_index.GetSize();
226 function_info.Clear();
227 if (count > 0)
228 function_info.Reserve(count);
229 for (size_t i = 0; i < count; ++i) {
230 const FDEEntryMap::Entry *func_offset_data_entry =
231 m_fde_index.GetEntryAtIndex(i);
232 if (func_offset_data_entry) {
233 FunctionAddressAndSizeVector::Entry function_offset_entry(
234 func_offset_data_entry->base, func_offset_data_entry->size);
235 function_info.Append(function_offset_entry);
Jason Molenda5635f772013-03-21 03:36:01 +0000236 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000237 }
Jason Molenda5635f772013-03-21 03:36:01 +0000238}
239
Kate Stoneb9c1b512016-09-06 20:57:50 +0000240const DWARFCallFrameInfo::CIE *
241DWARFCallFrameInfo::GetCIE(dw_offset_t cie_offset) {
242 cie_map_t::iterator pos = m_cie_map.find(cie_offset);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000243
Kate Stoneb9c1b512016-09-06 20:57:50 +0000244 if (pos != m_cie_map.end()) {
245 // Parse and cache the CIE
246 if (pos->second.get() == nullptr)
247 pos->second = ParseCIE(cie_offset);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000248
Kate Stoneb9c1b512016-09-06 20:57:50 +0000249 return pos->second.get();
250 }
251 return nullptr;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000252}
253
Jason Molendafbcb7f22010-09-10 07:49:16 +0000254DWARFCallFrameInfo::CIESP
Kate Stoneb9c1b512016-09-06 20:57:50 +0000255DWARFCallFrameInfo::ParseCIE(const dw_offset_t cie_offset) {
256 CIESP cie_sp(new CIE(cie_offset));
257 lldb::offset_t offset = cie_offset;
258 if (m_cfi_data_initialized == false)
259 GetCFIData();
260 uint32_t length = m_cfi_data.GetU32(&offset);
261 dw_offset_t cie_id, end_offset;
262 bool is_64bit = (length == UINT32_MAX);
263 if (is_64bit) {
264 length = m_cfi_data.GetU64(&offset);
265 cie_id = m_cfi_data.GetU64(&offset);
266 end_offset = cie_offset + length + 12;
267 } else {
268 cie_id = m_cfi_data.GetU32(&offset);
269 end_offset = cie_offset + length + 4;
270 }
271 if (length > 0 && ((!m_is_eh_frame && cie_id == UINT32_MAX) ||
272 (m_is_eh_frame && cie_id == 0ul))) {
273 size_t i;
274 // cie.offset = cie_offset;
275 // cie.length = length;
276 // cie.cieID = cieID;
277 cie_sp->ptr_encoding = DW_EH_PE_absptr; // default
278 cie_sp->version = m_cfi_data.GetU8(&offset);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000279
Kate Stoneb9c1b512016-09-06 20:57:50 +0000280 for (i = 0; i < CFI_AUG_MAX_SIZE; ++i) {
281 cie_sp->augmentation[i] = m_cfi_data.GetU8(&offset);
282 if (cie_sp->augmentation[i] == '\0') {
283 // Zero out remaining bytes in augmentation string
284 for (size_t j = i + 1; j < CFI_AUG_MAX_SIZE; ++j)
285 cie_sp->augmentation[j] = '\0';
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000286
Kate Stoneb9c1b512016-09-06 20:57:50 +0000287 break;
288 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000289 }
290
Kate Stoneb9c1b512016-09-06 20:57:50 +0000291 if (i == CFI_AUG_MAX_SIZE &&
292 cie_sp->augmentation[CFI_AUG_MAX_SIZE - 1] != '\0') {
293 Host::SystemLog(Host::eSystemLogError,
294 "CIE parse error: CIE augmentation string was too large "
295 "for the fixed sized buffer of %d bytes.\n",
296 CFI_AUG_MAX_SIZE);
297 return cie_sp;
298 }
299 cie_sp->code_align = (uint32_t)m_cfi_data.GetULEB128(&offset);
300 cie_sp->data_align = (int32_t)m_cfi_data.GetSLEB128(&offset);
301 cie_sp->return_addr_reg_num = m_cfi_data.GetU8(&offset);
302
303 if (cie_sp->augmentation[0]) {
304 // Get the length of the eh_frame augmentation data
305 // which starts with a ULEB128 length in bytes
306 const size_t aug_data_len = (size_t)m_cfi_data.GetULEB128(&offset);
307 const size_t aug_data_end = offset + aug_data_len;
308 const size_t aug_str_len = strlen(cie_sp->augmentation);
309 // A 'z' may be present as the first character of the string.
310 // If present, the Augmentation Data field shall be present.
311 // The contents of the Augmentation Data shall be interpreted
312 // according to other characters in the Augmentation String.
313 if (cie_sp->augmentation[0] == 'z') {
314 // Extract the Augmentation Data
315 size_t aug_str_idx = 0;
316 for (aug_str_idx = 1; aug_str_idx < aug_str_len; aug_str_idx++) {
317 char aug = cie_sp->augmentation[aug_str_idx];
318 switch (aug) {
319 case 'L':
320 // Indicates the presence of one argument in the
321 // Augmentation Data of the CIE, and a corresponding
322 // argument in the Augmentation Data of the FDE. The
323 // argument in the Augmentation Data of the CIE is
324 // 1-byte and represents the pointer encoding used
325 // for the argument in the Augmentation Data of the
326 // FDE, which is the address of a language-specific
327 // data area (LSDA). The size of the LSDA pointer is
328 // specified by the pointer encoding used.
329 cie_sp->lsda_addr_encoding = m_cfi_data.GetU8(&offset);
330 break;
331
332 case 'P':
333 // Indicates the presence of two arguments in the
334 // Augmentation Data of the CIE. The first argument
335 // is 1-byte and represents the pointer encoding
336 // used for the second argument, which is the
337 // address of a personality routine handler. The
338 // size of the personality routine pointer is
339 // specified by the pointer encoding used.
340 //
341 // The address of the personality function will
342 // be stored at this location. Pre-execution, it
343 // will be all zero's so don't read it until we're
344 // trying to do an unwind & the reloc has been
345 // resolved.
346 {
347 uint8_t arg_ptr_encoding = m_cfi_data.GetU8(&offset);
348 const lldb::addr_t pc_rel_addr = m_section_sp->GetFileAddress();
Zachary Turner29cb8682017-03-03 20:57:05 +0000349 cie_sp->personality_loc = GetGNUEHPointer(
350 m_cfi_data, &offset, arg_ptr_encoding, pc_rel_addr,
351 LLDB_INVALID_ADDRESS, LLDB_INVALID_ADDRESS);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000352 }
353 break;
354
355 case 'R':
356 // A 'R' may be present at any position after the
357 // first character of the string. The Augmentation
358 // Data shall include a 1 byte argument that
359 // represents the pointer encoding for the address
360 // pointers used in the FDE.
361 // Example: 0x1B == DW_EH_PE_pcrel | DW_EH_PE_sdata4
362 cie_sp->ptr_encoding = m_cfi_data.GetU8(&offset);
363 break;
364 }
365 }
366 } else if (strcmp(cie_sp->augmentation, "eh") == 0) {
367 // If the Augmentation string has the value "eh", then
368 // the EH Data field shall be present
369 }
370
371 // Set the offset to be the end of the augmentation data just in case
372 // we didn't understand any of the data.
373 offset = (uint32_t)aug_data_end;
374 }
375
376 if (end_offset > offset) {
377 cie_sp->inst_offset = offset;
378 cie_sp->inst_length = end_offset - offset;
379 }
380 while (offset < end_offset) {
381 uint8_t inst = m_cfi_data.GetU8(&offset);
382 uint8_t primary_opcode = inst & 0xC0;
383 uint8_t extended_opcode = inst & 0x3F;
384
385 if (!HandleCommonDwarfOpcode(primary_opcode, extended_opcode,
386 cie_sp->data_align, offset,
387 cie_sp->initial_row))
388 break; // Stop if we hit an unrecognized opcode
389 }
390 }
391
392 return cie_sp;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000393}
394
Kate Stoneb9c1b512016-09-06 20:57:50 +0000395void DWARFCallFrameInfo::GetCFIData() {
396 if (m_cfi_data_initialized == false) {
397 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND));
398 if (log)
399 m_objfile.GetModule()->LogMessage(log, "Reading EH frame info");
400 m_objfile.ReadSectionData(m_section_sp.get(), m_cfi_data);
401 m_cfi_data_initialized = true;
402 }
Greg Claytonf97c5212011-12-29 00:05:26 +0000403}
Kate Stoneb9c1b512016-09-06 20:57:50 +0000404// Scan through the eh_frame or debug_frame section looking for FDEs and noting
405// the start/end addresses
406// of the functions and a pointer back to the function's FDE for later
407// expansion.
Jason Molendafbcb7f22010-09-10 07:49:16 +0000408// Internalize CIEs as we come across them.
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000409
Kate Stoneb9c1b512016-09-06 20:57:50 +0000410void DWARFCallFrameInfo::GetFDEIndex() {
411 if (m_section_sp.get() == nullptr || m_section_sp->IsEncrypted())
412 return;
Saleem Abdulrasoolbb19a132016-05-19 05:13:57 +0000413
Kate Stoneb9c1b512016-09-06 20:57:50 +0000414 if (m_fde_index_initialized)
415 return;
Saleem Abdulrasoolbb19a132016-05-19 05:13:57 +0000416
Kate Stoneb9c1b512016-09-06 20:57:50 +0000417 std::lock_guard<std::mutex> guard(m_fde_index_mutex);
Jason Molendae6194f12010-10-26 12:01:35 +0000418
Kate Stoneb9c1b512016-09-06 20:57:50 +0000419 if (m_fde_index_initialized) // if two threads hit the locker
420 return;
Jason Molenda74303822013-03-20 21:57:42 +0000421
Kate Stoneb9c1b512016-09-06 20:57:50 +0000422 Timer scoped_timer(LLVM_PRETTY_FUNCTION, "%s - %s", LLVM_PRETTY_FUNCTION,
423 m_objfile.GetFileSpec().GetFilename().AsCString(""));
Jason Molendac7afda52016-06-07 02:19:54 +0000424
Kate Stoneb9c1b512016-09-06 20:57:50 +0000425 bool clear_address_zeroth_bit = false;
426 ArchSpec arch;
427 if (m_objfile.GetArchitecture(arch)) {
428 if (arch.GetTriple().getArch() == llvm::Triple::arm ||
429 arch.GetTriple().getArch() == llvm::Triple::thumb)
430 clear_address_zeroth_bit = true;
431 }
Jason Molendafbcb7f22010-09-10 07:49:16 +0000432
Kate Stoneb9c1b512016-09-06 20:57:50 +0000433 lldb::offset_t offset = 0;
434 if (m_cfi_data_initialized == false)
435 GetCFIData();
436 while (m_cfi_data.ValidOffsetForDataOfSize(offset, 8)) {
437 const dw_offset_t current_entry = offset;
438 dw_offset_t cie_id, next_entry, cie_offset;
439 uint32_t len = m_cfi_data.GetU32(&offset);
440 bool is_64bit = (len == UINT32_MAX);
Todd Fiala1767e112014-08-25 21:39:30 +0000441 if (is_64bit) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000442 len = m_cfi_data.GetU64(&offset);
443 cie_id = m_cfi_data.GetU64(&offset);
444 next_entry = current_entry + len + 12;
445 cie_offset = current_entry + 12 - cie_id;
Todd Fiala1767e112014-08-25 21:39:30 +0000446 } else {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000447 cie_id = m_cfi_data.GetU32(&offset);
448 next_entry = current_entry + len + 4;
449 cie_offset = current_entry + 4 - cie_id;
Todd Fiala1767e112014-08-25 21:39:30 +0000450 }
Jason Molendafbcb7f22010-09-10 07:49:16 +0000451
Kate Stoneb9c1b512016-09-06 20:57:50 +0000452 if (next_entry > m_cfi_data.GetByteSize() + 1) {
453 Host::SystemLog(Host::eSystemLogError, "error: Invalid fde/cie next "
454 "entry offset of 0x%x found in "
455 "cie/fde at 0x%x\n",
456 next_entry, current_entry);
457 // Don't trust anything in this eh_frame section if we find blatantly
458 // invalid data.
459 m_fde_index.Clear();
460 m_fde_index_initialized = true;
461 return;
Jason Molendaab4f1922010-10-25 11:12:07 +0000462 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000463 if (cie_offset > m_cfi_data.GetByteSize()) {
464 Host::SystemLog(
465 Host::eSystemLogError,
466 "error: Invalid cie offset of 0x%x found in cie/fde at 0x%x\n",
467 cie_offset, current_entry);
468 // Don't trust anything in this eh_frame section if we find blatantly
469 // invalid data.
470 m_fde_index.Clear();
471 m_fde_index_initialized = true;
472 return;
Jason Molendae9c7ecf2014-11-18 02:27:42 +0000473 }
474
Kate Stoneb9c1b512016-09-06 20:57:50 +0000475 if (cie_id == 0 || cie_id == UINT32_MAX || len == 0) {
476 m_cie_map[current_entry] = ParseCIE(current_entry);
477 offset = next_entry;
478 continue;
Jason Molendae9c7ecf2014-11-18 02:27:42 +0000479 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000480
Kate Stoneb9c1b512016-09-06 20:57:50 +0000481 const CIE *cie = GetCIE(cie_offset);
482 if (cie) {
483 const lldb::addr_t pc_rel_addr = m_section_sp->GetFileAddress();
484 const lldb::addr_t text_addr = LLDB_INVALID_ADDRESS;
485 const lldb::addr_t data_addr = LLDB_INVALID_ADDRESS;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000486
Zachary Turner29cb8682017-03-03 20:57:05 +0000487 lldb::addr_t addr =
488 GetGNUEHPointer(m_cfi_data, &offset, cie->ptr_encoding, pc_rel_addr,
489 text_addr, data_addr);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000490 if (clear_address_zeroth_bit)
491 addr &= ~1ull;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000492
Zachary Turner29cb8682017-03-03 20:57:05 +0000493 lldb::addr_t length = GetGNUEHPointer(
494 m_cfi_data, &offset, cie->ptr_encoding & DW_EH_PE_MASK_ENCODING,
495 pc_rel_addr, text_addr, data_addr);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000496 FDEEntryMap::Entry fde(addr, length, current_entry);
497 m_fde_index.Append(fde);
498 } else {
499 Host::SystemLog(Host::eSystemLogError, "error: unable to find CIE at "
500 "0x%8.8x for cie_id = 0x%8.8x for "
501 "entry at 0x%8.8x.\n",
502 cie_offset, cie_id, current_entry);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000503 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000504 offset = next_entry;
505 }
506 m_fde_index.Sort();
507 m_fde_index_initialized = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000508}
Tamas Berghammer623652a2015-07-03 09:30:17 +0000509
Kate Stoneb9c1b512016-09-06 20:57:50 +0000510bool DWARFCallFrameInfo::FDEToUnwindPlan(dw_offset_t dwarf_offset,
511 Address startaddr,
512 UnwindPlan &unwind_plan) {
513 Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND);
514 lldb::offset_t offset = dwarf_offset;
515 lldb::offset_t current_entry = offset;
Tamas Berghammer623652a2015-07-03 09:30:17 +0000516
Kate Stoneb9c1b512016-09-06 20:57:50 +0000517 if (m_section_sp.get() == nullptr || m_section_sp->IsEncrypted())
Tamas Berghammer623652a2015-07-03 09:30:17 +0000518 return false;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000519
520 if (m_cfi_data_initialized == false)
521 GetCFIData();
522
523 uint32_t length = m_cfi_data.GetU32(&offset);
524 dw_offset_t cie_offset;
525 bool is_64bit = (length == UINT32_MAX);
526 if (is_64bit) {
527 length = m_cfi_data.GetU64(&offset);
528 cie_offset = m_cfi_data.GetU64(&offset);
529 } else {
530 cie_offset = m_cfi_data.GetU32(&offset);
531 }
532
533 assert(cie_offset != 0 && cie_offset != UINT32_MAX);
534
535 // Translate the CIE_id from the eh_frame format, which
536 // is relative to the FDE offset, into a __eh_frame section
537 // offset
538 if (m_is_eh_frame) {
539 unwind_plan.SetSourceName("eh_frame CFI");
540 cie_offset = current_entry + (is_64bit ? 12 : 4) - cie_offset;
541 unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
542 } else {
543 unwind_plan.SetSourceName("DWARF CFI");
544 // In theory the debug_frame info should be valid at all call sites
545 // ("asynchronous unwind info" as it is sometimes called) but in practice
546 // gcc et al all emit call frame info for the prologue and call sites, but
547 // not for the epilogue or all the other locations during the function
548 // reliably.
549 unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
550 }
551 unwind_plan.SetSourcedFromCompiler(eLazyBoolYes);
552
553 const CIE *cie = GetCIE(cie_offset);
554 assert(cie != nullptr);
555
556 const dw_offset_t end_offset = current_entry + length + (is_64bit ? 12 : 4);
557
558 const lldb::addr_t pc_rel_addr = m_section_sp->GetFileAddress();
559 const lldb::addr_t text_addr = LLDB_INVALID_ADDRESS;
560 const lldb::addr_t data_addr = LLDB_INVALID_ADDRESS;
Zachary Turner29cb8682017-03-03 20:57:05 +0000561 lldb::addr_t range_base =
562 GetGNUEHPointer(m_cfi_data, &offset, cie->ptr_encoding, pc_rel_addr,
563 text_addr, data_addr);
564 lldb::addr_t range_len = GetGNUEHPointer(
565 m_cfi_data, &offset, cie->ptr_encoding & DW_EH_PE_MASK_ENCODING,
566 pc_rel_addr, text_addr, data_addr);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000567 AddressRange range(range_base, m_objfile.GetAddressByteSize(),
568 m_objfile.GetSectionList());
569 range.SetByteSize(range_len);
570
571 addr_t lsda_data_file_address = LLDB_INVALID_ADDRESS;
572
573 if (cie->augmentation[0] == 'z') {
574 uint32_t aug_data_len = (uint32_t)m_cfi_data.GetULEB128(&offset);
575 if (aug_data_len != 0 && cie->lsda_addr_encoding != DW_EH_PE_omit) {
576 offset_t saved_offset = offset;
Zachary Turner29cb8682017-03-03 20:57:05 +0000577 lsda_data_file_address =
578 GetGNUEHPointer(m_cfi_data, &offset, cie->lsda_addr_encoding,
579 pc_rel_addr, text_addr, data_addr);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000580 if (offset - saved_offset != aug_data_len) {
581 // There is more in the augmentation region than we know how to process;
582 // don't read anything.
583 lsda_data_file_address = LLDB_INVALID_ADDRESS;
584 }
585 offset = saved_offset;
586 }
587 offset += aug_data_len;
588 }
589 Address lsda_data;
590 Address personality_function_ptr;
591
592 if (lsda_data_file_address != LLDB_INVALID_ADDRESS &&
593 cie->personality_loc != LLDB_INVALID_ADDRESS) {
594 m_objfile.GetModule()->ResolveFileAddress(lsda_data_file_address,
595 lsda_data);
596 m_objfile.GetModule()->ResolveFileAddress(cie->personality_loc,
597 personality_function_ptr);
598 }
599
600 if (lsda_data.IsValid() && personality_function_ptr.IsValid()) {
601 unwind_plan.SetLSDAAddress(lsda_data);
602 unwind_plan.SetPersonalityFunctionPtr(personality_function_ptr);
603 }
604
605 uint32_t code_align = cie->code_align;
606 int32_t data_align = cie->data_align;
607
608 unwind_plan.SetPlanValidAddressRange(range);
609 UnwindPlan::Row *cie_initial_row = new UnwindPlan::Row;
610 *cie_initial_row = cie->initial_row;
611 UnwindPlan::RowSP row(cie_initial_row);
612
613 unwind_plan.SetRegisterKind(m_reg_kind);
614 unwind_plan.SetReturnAddressRegister(cie->return_addr_reg_num);
615
616 std::vector<UnwindPlan::RowSP> stack;
617
618 UnwindPlan::Row::RegisterLocation reg_location;
619 while (m_cfi_data.ValidOffset(offset) && offset < end_offset) {
620 uint8_t inst = m_cfi_data.GetU8(&offset);
621 uint8_t primary_opcode = inst & 0xC0;
622 uint8_t extended_opcode = inst & 0x3F;
623
624 if (!HandleCommonDwarfOpcode(primary_opcode, extended_opcode, data_align,
625 offset, *row)) {
626 if (primary_opcode) {
627 switch (primary_opcode) {
628 case DW_CFA_advance_loc: // (Row Creation Instruction)
629 { // 0x40 - high 2 bits are 0x1, lower 6 bits are delta
630 // takes a single argument that represents a constant delta. The
631 // required action is to create a new table row with a location
632 // value that is computed by taking the current entry's location
633 // value and adding (delta * code_align). All other
634 // values in the new row are initially identical to the current row.
635 unwind_plan.AppendRow(row);
636 UnwindPlan::Row *newrow = new UnwindPlan::Row;
637 *newrow = *row.get();
638 row.reset(newrow);
639 row->SlideOffset(extended_opcode * code_align);
640 break;
641 }
642
643 case DW_CFA_restore: { // 0xC0 - high 2 bits are 0x3, lower 6 bits are
644 // register
645 // takes a single argument that represents a register number. The
646 // required action is to change the rule for the indicated register
647 // to the rule assigned it by the initial_instructions in the CIE.
648 uint32_t reg_num = extended_opcode;
649 // We only keep enough register locations around to
650 // unwind what is in our thread, and these are organized
651 // by the register index in that state, so we need to convert our
652 // eh_frame register number from the EH frame info, to a register
653 // index
654
655 if (unwind_plan.IsValidRowIndex(0) &&
656 unwind_plan.GetRowAtIndex(0)->GetRegisterInfo(reg_num,
657 reg_location))
658 row->SetRegisterInfo(reg_num, reg_location);
659 break;
660 }
661 }
662 } else {
663 switch (extended_opcode) {
664 case DW_CFA_set_loc: // 0x1 (Row Creation Instruction)
665 {
666 // DW_CFA_set_loc takes a single argument that represents an address.
667 // The required action is to create a new table row using the
668 // specified address as the location. All other values in the new row
669 // are initially identical to the current row. The new location value
670 // should always be greater than the current one.
671 unwind_plan.AppendRow(row);
672 UnwindPlan::Row *newrow = new UnwindPlan::Row;
673 *newrow = *row.get();
674 row.reset(newrow);
675 row->SetOffset(m_cfi_data.GetPointer(&offset) -
676 startaddr.GetFileAddress());
677 break;
678 }
679
680 case DW_CFA_advance_loc1: // 0x2 (Row Creation Instruction)
681 {
682 // takes a single uword argument that represents a constant delta.
683 // This instruction is identical to DW_CFA_advance_loc except for the
684 // encoding and size of the delta argument.
685 unwind_plan.AppendRow(row);
686 UnwindPlan::Row *newrow = new UnwindPlan::Row;
687 *newrow = *row.get();
688 row.reset(newrow);
689 row->SlideOffset(m_cfi_data.GetU8(&offset) * code_align);
690 break;
691 }
692
693 case DW_CFA_advance_loc2: // 0x3 (Row Creation Instruction)
694 {
695 // takes a single uword argument that represents a constant delta.
696 // This instruction is identical to DW_CFA_advance_loc except for the
697 // encoding and size of the delta argument.
698 unwind_plan.AppendRow(row);
699 UnwindPlan::Row *newrow = new UnwindPlan::Row;
700 *newrow = *row.get();
701 row.reset(newrow);
702 row->SlideOffset(m_cfi_data.GetU16(&offset) * code_align);
703 break;
704 }
705
706 case DW_CFA_advance_loc4: // 0x4 (Row Creation Instruction)
707 {
708 // takes a single uword argument that represents a constant delta.
709 // This instruction is identical to DW_CFA_advance_loc except for the
710 // encoding and size of the delta argument.
711 unwind_plan.AppendRow(row);
712 UnwindPlan::Row *newrow = new UnwindPlan::Row;
713 *newrow = *row.get();
714 row.reset(newrow);
715 row->SlideOffset(m_cfi_data.GetU32(&offset) * code_align);
716 break;
717 }
718
719 case DW_CFA_restore_extended: // 0x6
720 {
721 // takes a single unsigned LEB128 argument that represents a register
722 // number. This instruction is identical to DW_CFA_restore except for
723 // the encoding and size of the register argument.
724 uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);
725 if (unwind_plan.IsValidRowIndex(0) &&
726 unwind_plan.GetRowAtIndex(0)->GetRegisterInfo(reg_num,
727 reg_location))
728 row->SetRegisterInfo(reg_num, reg_location);
729 break;
730 }
731
732 case DW_CFA_remember_state: // 0xA
733 {
734 // These instructions define a stack of information. Encountering the
735 // DW_CFA_remember_state instruction means to save the rules for every
736 // register on the current row on the stack. Encountering the
737 // DW_CFA_restore_state instruction means to pop the set of rules off
738 // the stack and place them in the current row. (This operation is
739 // useful for compilers that move epilogue code into the body of a
740 // function.)
741 stack.push_back(row);
742 UnwindPlan::Row *newrow = new UnwindPlan::Row;
743 *newrow = *row.get();
744 row.reset(newrow);
745 break;
746 }
747
748 case DW_CFA_restore_state: // 0xB
749 {
750 // These instructions define a stack of information. Encountering the
751 // DW_CFA_remember_state instruction means to save the rules for every
752 // register on the current row on the stack. Encountering the
753 // DW_CFA_restore_state instruction means to pop the set of rules off
754 // the stack and place them in the current row. (This operation is
755 // useful for compilers that move epilogue code into the body of a
756 // function.)
757 if (stack.empty()) {
758 if (log)
759 log->Printf("DWARFCallFrameInfo::%s(dwarf_offset: %" PRIx32
760 ", startaddr: %" PRIx64
761 " encountered DW_CFA_restore_state but state stack "
762 "is empty. Corrupt unwind info?",
763 __FUNCTION__, dwarf_offset,
764 startaddr.GetFileAddress());
765 break;
766 }
767 lldb::addr_t offset = row->GetOffset();
768 row = stack.back();
769 stack.pop_back();
770 row->SetOffset(offset);
771 break;
772 }
773
774 case DW_CFA_GNU_args_size: // 0x2e
775 {
776 // The DW_CFA_GNU_args_size instruction takes an unsigned LEB128
777 // operand
778 // representing an argument size. This instruction specifies the total
779 // of
780 // the size of the arguments which have been pushed onto the stack.
781
782 // TODO: Figure out how we should handle this.
783 m_cfi_data.GetULEB128(&offset);
784 break;
785 }
786
787 case DW_CFA_val_offset: // 0x14
788 case DW_CFA_val_offset_sf: // 0x15
789 default:
790 break;
791 }
792 }
793 }
794 }
795 unwind_plan.AppendRow(row);
796
797 return true;
Tamas Berghammer623652a2015-07-03 09:30:17 +0000798}
Tamas Berghammer6b63b142016-02-18 11:12:18 +0000799
Kate Stoneb9c1b512016-09-06 20:57:50 +0000800bool DWARFCallFrameInfo::HandleCommonDwarfOpcode(uint8_t primary_opcode,
801 uint8_t extended_opcode,
802 int32_t data_align,
803 lldb::offset_t &offset,
804 UnwindPlan::Row &row) {
805 UnwindPlan::Row::RegisterLocation reg_location;
Tamas Berghammer6b63b142016-02-18 11:12:18 +0000806
Kate Stoneb9c1b512016-09-06 20:57:50 +0000807 if (primary_opcode) {
808 switch (primary_opcode) {
809 case DW_CFA_offset: { // 0x80 - high 2 bits are 0x2, lower 6 bits are
810 // register
811 // takes two arguments: an unsigned LEB128 constant representing a
812 // factored offset and a register number. The required action is to
813 // change the rule for the register indicated by the register number
814 // to be an offset(N) rule with a value of
815 // (N = factored offset * data_align).
816 uint8_t reg_num = extended_opcode;
817 int32_t op_offset = (int32_t)m_cfi_data.GetULEB128(&offset) * data_align;
818 reg_location.SetAtCFAPlusOffset(op_offset);
819 row.SetRegisterInfo(reg_num, reg_location);
820 return true;
Tamas Berghammer6b63b142016-02-18 11:12:18 +0000821 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000822 }
823 } else {
824 switch (extended_opcode) {
825 case DW_CFA_nop: // 0x0
826 return true;
827
828 case DW_CFA_offset_extended: // 0x5
829 {
830 // takes two unsigned LEB128 arguments representing a register number
831 // and a factored offset. This instruction is identical to DW_CFA_offset
832 // except for the encoding and size of the register argument.
833 uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);
834 int32_t op_offset = (int32_t)m_cfi_data.GetULEB128(&offset) * data_align;
835 UnwindPlan::Row::RegisterLocation reg_location;
836 reg_location.SetAtCFAPlusOffset(op_offset);
837 row.SetRegisterInfo(reg_num, reg_location);
838 return true;
839 }
840
841 case DW_CFA_undefined: // 0x7
842 {
843 // takes a single unsigned LEB128 argument that represents a register
844 // number. The required action is to set the rule for the specified
845 // register to undefined.
846 uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);
847 UnwindPlan::Row::RegisterLocation reg_location;
848 reg_location.SetUndefined();
849 row.SetRegisterInfo(reg_num, reg_location);
850 return true;
851 }
852
853 case DW_CFA_same_value: // 0x8
854 {
855 // takes a single unsigned LEB128 argument that represents a register
856 // number. The required action is to set the rule for the specified
857 // register to same value.
858 uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);
859 UnwindPlan::Row::RegisterLocation reg_location;
860 reg_location.SetSame();
861 row.SetRegisterInfo(reg_num, reg_location);
862 return true;
863 }
864
865 case DW_CFA_register: // 0x9
866 {
867 // takes two unsigned LEB128 arguments representing register numbers.
868 // The required action is to set the rule for the first register to be
869 // the second register.
870 uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);
871 uint32_t other_reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);
872 UnwindPlan::Row::RegisterLocation reg_location;
873 reg_location.SetInRegister(other_reg_num);
874 row.SetRegisterInfo(reg_num, reg_location);
875 return true;
876 }
877
878 case DW_CFA_def_cfa: // 0xC (CFA Definition Instruction)
879 {
880 // Takes two unsigned LEB128 operands representing a register
881 // number and a (non-factored) offset. The required action
882 // is to define the current CFA rule to use the provided
883 // register and offset.
884 uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);
885 int32_t op_offset = (int32_t)m_cfi_data.GetULEB128(&offset);
886 row.GetCFAValue().SetIsRegisterPlusOffset(reg_num, op_offset);
887 return true;
888 }
889
890 case DW_CFA_def_cfa_register: // 0xD (CFA Definition Instruction)
891 {
892 // takes a single unsigned LEB128 argument representing a register
893 // number. The required action is to define the current CFA rule to
894 // use the provided register (but to keep the old offset).
895 uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);
896 row.GetCFAValue().SetIsRegisterPlusOffset(reg_num,
897 row.GetCFAValue().GetOffset());
898 return true;
899 }
900
901 case DW_CFA_def_cfa_offset: // 0xE (CFA Definition Instruction)
902 {
903 // Takes a single unsigned LEB128 operand representing a
904 // (non-factored) offset. The required action is to define
905 // the current CFA rule to use the provided offset (but
906 // to keep the old register).
907 int32_t op_offset = (int32_t)m_cfi_data.GetULEB128(&offset);
908 row.GetCFAValue().SetIsRegisterPlusOffset(
909 row.GetCFAValue().GetRegisterNumber(), op_offset);
910 return true;
911 }
912
913 case DW_CFA_def_cfa_expression: // 0xF (CFA Definition Instruction)
914 {
915 size_t block_len = (size_t)m_cfi_data.GetULEB128(&offset);
916 const uint8_t *block_data =
917 static_cast<const uint8_t *>(m_cfi_data.GetData(&offset, block_len));
918 row.GetCFAValue().SetIsDWARFExpression(block_data, block_len);
919 return true;
920 }
921
922 case DW_CFA_expression: // 0x10
923 {
924 // Takes two operands: an unsigned LEB128 value representing
925 // a register number, and a DW_FORM_block value representing a DWARF
926 // expression. The required action is to change the rule for the
927 // register indicated by the register number to be an expression(E)
928 // rule where E is the DWARF expression. That is, the DWARF
929 // expression computes the address. The value of the CFA is
930 // pushed on the DWARF evaluation stack prior to execution of
931 // the DWARF expression.
932 uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);
933 uint32_t block_len = (uint32_t)m_cfi_data.GetULEB128(&offset);
934 const uint8_t *block_data =
935 static_cast<const uint8_t *>(m_cfi_data.GetData(&offset, block_len));
936 UnwindPlan::Row::RegisterLocation reg_location;
937 reg_location.SetAtDWARFExpression(block_data, block_len);
938 row.SetRegisterInfo(reg_num, reg_location);
939 return true;
940 }
941
942 case DW_CFA_offset_extended_sf: // 0x11
943 {
944 // takes two operands: an unsigned LEB128 value representing a
945 // register number and a signed LEB128 factored offset. This
946 // instruction is identical to DW_CFA_offset_extended except
947 // that the second operand is signed and factored.
948 uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);
949 int32_t op_offset = (int32_t)m_cfi_data.GetSLEB128(&offset) * data_align;
950 UnwindPlan::Row::RegisterLocation reg_location;
951 reg_location.SetAtCFAPlusOffset(op_offset);
952 row.SetRegisterInfo(reg_num, reg_location);
953 return true;
954 }
955
956 case DW_CFA_def_cfa_sf: // 0x12 (CFA Definition Instruction)
957 {
958 // Takes two operands: an unsigned LEB128 value representing
959 // a register number and a signed LEB128 factored offset.
960 // This instruction is identical to DW_CFA_def_cfa except
961 // that the second operand is signed and factored.
962 uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);
963 int32_t op_offset = (int32_t)m_cfi_data.GetSLEB128(&offset) * data_align;
964 row.GetCFAValue().SetIsRegisterPlusOffset(reg_num, op_offset);
965 return true;
966 }
967
968 case DW_CFA_def_cfa_offset_sf: // 0x13 (CFA Definition Instruction)
969 {
970 // takes a signed LEB128 operand representing a factored
971 // offset. This instruction is identical to DW_CFA_def_cfa_offset
972 // except that the operand is signed and factored.
973 int32_t op_offset = (int32_t)m_cfi_data.GetSLEB128(&offset) * data_align;
974 uint32_t cfa_regnum = row.GetCFAValue().GetRegisterNumber();
975 row.GetCFAValue().SetIsRegisterPlusOffset(cfa_regnum, op_offset);
976 return true;
977 }
978
979 case DW_CFA_val_expression: // 0x16
980 {
981 // takes two operands: an unsigned LEB128 value representing a register
982 // number, and a DW_FORM_block value representing a DWARF expression.
983 // The required action is to change the rule for the register indicated
984 // by the register number to be a val_expression(E) rule where E is the
985 // DWARF expression. That is, the DWARF expression computes the value of
986 // the given register. The value of the CFA is pushed on the DWARF
987 // evaluation stack prior to execution of the DWARF expression.
988 uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset);
989 uint32_t block_len = (uint32_t)m_cfi_data.GetULEB128(&offset);
990 const uint8_t *block_data =
991 (const uint8_t *)m_cfi_data.GetData(&offset, block_len);
992 //#if defined(__i386__) || defined(__x86_64__)
993 // // The EH frame info for EIP and RIP contains code that
994 // looks for traps to
995 // // be a specific type and increments the PC.
996 // // For i386:
997 // // DW_CFA_val_expression where:
998 // // eip = DW_OP_breg6(+28), DW_OP_deref, DW_OP_dup,
999 // DW_OP_plus_uconst(0x34),
1000 // // DW_OP_deref, DW_OP_swap, DW_OP_plus_uconst(0),
1001 // DW_OP_deref,
1002 // // DW_OP_dup, DW_OP_lit3, DW_OP_ne, DW_OP_swap,
1003 // DW_OP_lit4, DW_OP_ne,
1004 // // DW_OP_and, DW_OP_plus
1005 // // This basically does a:
1006 // // eip = ucontenxt.mcontext32->gpr.eip;
1007 // // if (ucontenxt.mcontext32->exc.trapno != 3 &&
1008 // ucontenxt.mcontext32->exc.trapno != 4)
1009 // // eip++;
1010 // //
1011 // // For x86_64:
1012 // // DW_CFA_val_expression where:
1013 // // rip = DW_OP_breg3(+48), DW_OP_deref, DW_OP_dup,
1014 // DW_OP_plus_uconst(0x90), DW_OP_deref,
1015 // // DW_OP_swap, DW_OP_plus_uconst(0),
1016 // DW_OP_deref_size(4), DW_OP_dup, DW_OP_lit3,
1017 // // DW_OP_ne, DW_OP_swap, DW_OP_lit4, DW_OP_ne,
1018 // DW_OP_and, DW_OP_plus
1019 // // This basically does a:
1020 // // rip = ucontenxt.mcontext64->gpr.rip;
1021 // // if (ucontenxt.mcontext64->exc.trapno != 3 &&
1022 // ucontenxt.mcontext64->exc.trapno != 4)
1023 // // rip++;
1024 // // The trap comparisons and increments are not needed as
1025 // it hoses up the unwound PC which
1026 // // is expected to point at least past the instruction that
1027 // causes the fault/trap. So we
1028 // // take it out by trimming the expression right at the
1029 // first "DW_OP_swap" opcodes
1030 // if (block_data != NULL && thread->GetPCRegNum(Thread::GCC)
1031 // == reg_num)
1032 // {
1033 // if (thread->Is64Bit())
1034 // {
1035 // if (block_len > 9 && block_data[8] == DW_OP_swap
1036 // && block_data[9] == DW_OP_plus_uconst)
1037 // block_len = 8;
1038 // }
1039 // else
1040 // {
1041 // if (block_len > 8 && block_data[7] == DW_OP_swap
1042 // && block_data[8] == DW_OP_plus_uconst)
1043 // block_len = 7;
1044 // }
1045 // }
1046 //#endif
1047 reg_location.SetIsDWARFExpression(block_data, block_len);
1048 row.SetRegisterInfo(reg_num, reg_location);
1049 return true;
1050 }
1051 }
1052 }
1053 return false;
1054}
1055
1056void DWARFCallFrameInfo::ForEachFDEEntries(
1057 const std::function<bool(lldb::addr_t, uint32_t, dw_offset_t)> &callback) {
1058 GetFDEIndex();
1059
1060 for (size_t i = 0, c = m_fde_index.GetSize(); i < c; ++i) {
1061 const FDEEntryMap::Entry &entry = m_fde_index.GetEntryRef(i);
1062 if (!callback(entry.base, entry.size, entry.data))
1063 break;
1064 }
Tamas Berghammer6b63b142016-02-18 11:12:18 +00001065}