]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/lldb/source/Symbol/CompactUnwindInfo.cpp
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm-project / lldb / source / Symbol / CompactUnwindInfo.cpp
1 //===-- CompactUnwindInfo.cpp -----------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "lldb/Symbol/CompactUnwindInfo.h"
10 #include "lldb/Core/Module.h"
11 #include "lldb/Core/Section.h"
12 #include "lldb/Symbol/ObjectFile.h"
13 #include "lldb/Symbol/UnwindPlan.h"
14 #include "lldb/Target/Process.h"
15 #include "lldb/Target/Target.h"
16 #include "lldb/Utility/ArchSpec.h"
17 #include "lldb/Utility/DataBufferHeap.h"
18 #include "lldb/Utility/Log.h"
19 #include "lldb/Utility/StreamString.h"
20
21 #include "llvm/Support/MathExtras.h"
22
23 #include <algorithm>
24 #include <memory>
25
26 using namespace lldb;
27 using namespace lldb_private;
28
29 namespace lldb_private {
30
31 // Constants from <mach-o/compact_unwind_encoding.h>
32
33 FLAGS_ANONYMOUS_ENUM(){
34     UNWIND_IS_NOT_FUNCTION_START = 0x80000000, UNWIND_HAS_LSDA = 0x40000000,
35     UNWIND_PERSONALITY_MASK = 0x30000000,
36 };
37
38 FLAGS_ANONYMOUS_ENUM(){
39     UNWIND_X86_MODE_MASK = 0x0F000000,
40     UNWIND_X86_MODE_EBP_FRAME = 0x01000000,
41     UNWIND_X86_MODE_STACK_IMMD = 0x02000000,
42     UNWIND_X86_MODE_STACK_IND = 0x03000000,
43     UNWIND_X86_MODE_DWARF = 0x04000000,
44
45     UNWIND_X86_EBP_FRAME_REGISTERS = 0x00007FFF,
46     UNWIND_X86_EBP_FRAME_OFFSET = 0x00FF0000,
47
48     UNWIND_X86_FRAMELESS_STACK_SIZE = 0x00FF0000,
49     UNWIND_X86_FRAMELESS_STACK_ADJUST = 0x0000E000,
50     UNWIND_X86_FRAMELESS_STACK_REG_COUNT = 0x00001C00,
51     UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION = 0x000003FF,
52
53     UNWIND_X86_DWARF_SECTION_OFFSET = 0x00FFFFFF,
54 };
55
56 enum {
57   UNWIND_X86_REG_NONE = 0,
58   UNWIND_X86_REG_EBX = 1,
59   UNWIND_X86_REG_ECX = 2,
60   UNWIND_X86_REG_EDX = 3,
61   UNWIND_X86_REG_EDI = 4,
62   UNWIND_X86_REG_ESI = 5,
63   UNWIND_X86_REG_EBP = 6,
64 };
65
66 FLAGS_ANONYMOUS_ENUM(){
67     UNWIND_X86_64_MODE_MASK = 0x0F000000,
68     UNWIND_X86_64_MODE_RBP_FRAME = 0x01000000,
69     UNWIND_X86_64_MODE_STACK_IMMD = 0x02000000,
70     UNWIND_X86_64_MODE_STACK_IND = 0x03000000,
71     UNWIND_X86_64_MODE_DWARF = 0x04000000,
72
73     UNWIND_X86_64_RBP_FRAME_REGISTERS = 0x00007FFF,
74     UNWIND_X86_64_RBP_FRAME_OFFSET = 0x00FF0000,
75
76     UNWIND_X86_64_FRAMELESS_STACK_SIZE = 0x00FF0000,
77     UNWIND_X86_64_FRAMELESS_STACK_ADJUST = 0x0000E000,
78     UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT = 0x00001C00,
79     UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION = 0x000003FF,
80
81     UNWIND_X86_64_DWARF_SECTION_OFFSET = 0x00FFFFFF,
82 };
83
84 enum {
85   UNWIND_X86_64_REG_NONE = 0,
86   UNWIND_X86_64_REG_RBX = 1,
87   UNWIND_X86_64_REG_R12 = 2,
88   UNWIND_X86_64_REG_R13 = 3,
89   UNWIND_X86_64_REG_R14 = 4,
90   UNWIND_X86_64_REG_R15 = 5,
91   UNWIND_X86_64_REG_RBP = 6,
92 };
93
94 FLAGS_ANONYMOUS_ENUM(){
95     UNWIND_ARM64_MODE_MASK = 0x0F000000,
96     UNWIND_ARM64_MODE_FRAMELESS = 0x02000000,
97     UNWIND_ARM64_MODE_DWARF = 0x03000000,
98     UNWIND_ARM64_MODE_FRAME = 0x04000000,
99
100     UNWIND_ARM64_FRAME_X19_X20_PAIR = 0x00000001,
101     UNWIND_ARM64_FRAME_X21_X22_PAIR = 0x00000002,
102     UNWIND_ARM64_FRAME_X23_X24_PAIR = 0x00000004,
103     UNWIND_ARM64_FRAME_X25_X26_PAIR = 0x00000008,
104     UNWIND_ARM64_FRAME_X27_X28_PAIR = 0x00000010,
105     UNWIND_ARM64_FRAME_D8_D9_PAIR = 0x00000100,
106     UNWIND_ARM64_FRAME_D10_D11_PAIR = 0x00000200,
107     UNWIND_ARM64_FRAME_D12_D13_PAIR = 0x00000400,
108     UNWIND_ARM64_FRAME_D14_D15_PAIR = 0x00000800,
109
110     UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK = 0x00FFF000,
111     UNWIND_ARM64_DWARF_SECTION_OFFSET = 0x00FFFFFF,
112 };
113
114 FLAGS_ANONYMOUS_ENUM(){
115     UNWIND_ARM_MODE_MASK = 0x0F000000,
116     UNWIND_ARM_MODE_FRAME = 0x01000000,
117     UNWIND_ARM_MODE_FRAME_D = 0x02000000,
118     UNWIND_ARM_MODE_DWARF = 0x04000000,
119
120     UNWIND_ARM_FRAME_STACK_ADJUST_MASK = 0x00C00000,
121
122     UNWIND_ARM_FRAME_FIRST_PUSH_R4 = 0x00000001,
123     UNWIND_ARM_FRAME_FIRST_PUSH_R5 = 0x00000002,
124     UNWIND_ARM_FRAME_FIRST_PUSH_R6 = 0x00000004,
125
126     UNWIND_ARM_FRAME_SECOND_PUSH_R8 = 0x00000008,
127     UNWIND_ARM_FRAME_SECOND_PUSH_R9 = 0x00000010,
128     UNWIND_ARM_FRAME_SECOND_PUSH_R10 = 0x00000020,
129     UNWIND_ARM_FRAME_SECOND_PUSH_R11 = 0x00000040,
130     UNWIND_ARM_FRAME_SECOND_PUSH_R12 = 0x00000080,
131
132     UNWIND_ARM_FRAME_D_REG_COUNT_MASK = 0x00000700,
133
134     UNWIND_ARM_DWARF_SECTION_OFFSET = 0x00FFFFFF,
135 };
136 }
137
138 #ifndef UNWIND_SECOND_LEVEL_REGULAR
139 #define UNWIND_SECOND_LEVEL_REGULAR 2
140 #endif
141
142 #ifndef UNWIND_SECOND_LEVEL_COMPRESSED
143 #define UNWIND_SECOND_LEVEL_COMPRESSED 3
144 #endif
145
146 #ifndef UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET
147 #define UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET(entry) (entry & 0x00FFFFFF)
148 #endif
149
150 #ifndef UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX
151 #define UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX(entry)                     \
152   ((entry >> 24) & 0xFF)
153 #endif
154
155 #define EXTRACT_BITS(value, mask)                                              \
156   ((value >>                                                                   \
157     llvm::countTrailingZeros(static_cast<uint32_t>(mask), llvm::ZB_Width)) &   \
158    (((1 << llvm::countPopulation(static_cast<uint32_t>(mask)))) - 1))
159
160 // constructor
161
162 CompactUnwindInfo::CompactUnwindInfo(ObjectFile &objfile, SectionSP &section_sp)
163     : m_objfile(objfile), m_section_sp(section_sp),
164       m_section_contents_if_encrypted(), m_mutex(), m_indexes(),
165       m_indexes_computed(eLazyBoolCalculate), m_unwindinfo_data(),
166       m_unwindinfo_data_computed(false), m_unwind_header() {}
167
168 // destructor
169
170 CompactUnwindInfo::~CompactUnwindInfo() {}
171
172 bool CompactUnwindInfo::GetUnwindPlan(Target &target, Address addr,
173                                       UnwindPlan &unwind_plan) {
174   if (!IsValid(target.GetProcessSP())) {
175     return false;
176   }
177   FunctionInfo function_info;
178   if (GetCompactUnwindInfoForFunction(target, addr, function_info)) {
179     // shortcut return for functions that have no compact unwind
180     if (function_info.encoding == 0)
181       return false;
182
183     if (ArchSpec arch = m_objfile.GetArchitecture()) {
184
185       Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND));
186       if (log && log->GetVerbose()) {
187         StreamString strm;
188         addr.Dump(
189             &strm, nullptr,
190             Address::DumpStyle::DumpStyleResolvedDescriptionNoFunctionArguments,
191             Address::DumpStyle::DumpStyleFileAddress,
192             arch.GetAddressByteSize());
193         LLDB_LOGF(log, "Got compact unwind encoding 0x%x for function %s",
194                   function_info.encoding, strm.GetData());
195       }
196
197       if (function_info.valid_range_offset_start != 0 &&
198           function_info.valid_range_offset_end != 0) {
199         SectionList *sl = m_objfile.GetSectionList();
200         if (sl) {
201           addr_t func_range_start_file_addr =
202               function_info.valid_range_offset_start +
203               m_objfile.GetBaseAddress().GetFileAddress();
204           AddressRange func_range(func_range_start_file_addr,
205                                   function_info.valid_range_offset_end -
206                                       function_info.valid_range_offset_start,
207                                   sl);
208           unwind_plan.SetPlanValidAddressRange(func_range);
209         }
210       }
211
212       if (arch.GetTriple().getArch() == llvm::Triple::x86_64) {
213         return CreateUnwindPlan_x86_64(target, function_info, unwind_plan,
214                                        addr);
215       }
216       if (arch.GetTriple().getArch() == llvm::Triple::aarch64 ||
217           arch.GetTriple().getArch() == llvm::Triple::aarch64_32) {
218         return CreateUnwindPlan_arm64(target, function_info, unwind_plan, addr);
219       }
220       if (arch.GetTriple().getArch() == llvm::Triple::x86) {
221         return CreateUnwindPlan_i386(target, function_info, unwind_plan, addr);
222       }
223       if (arch.GetTriple().getArch() == llvm::Triple::arm ||
224           arch.GetTriple().getArch() == llvm::Triple::thumb) {
225         return CreateUnwindPlan_armv7(target, function_info, unwind_plan, addr);
226       }
227     }
228   }
229   return false;
230 }
231
232 bool CompactUnwindInfo::IsValid(const ProcessSP &process_sp) {
233   if (m_section_sp.get() == nullptr)
234     return false;
235
236   if (m_indexes_computed == eLazyBoolYes && m_unwindinfo_data_computed)
237     return true;
238
239   ScanIndex(process_sp);
240
241   return m_indexes_computed == eLazyBoolYes && m_unwindinfo_data_computed;
242 }
243
244 void CompactUnwindInfo::ScanIndex(const ProcessSP &process_sp) {
245   std::lock_guard<std::mutex> guard(m_mutex);
246   if (m_indexes_computed == eLazyBoolYes && m_unwindinfo_data_computed)
247     return;
248
249   // We can't read the index for some reason.
250   if (m_indexes_computed == eLazyBoolNo) {
251     return;
252   }
253
254   Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND));
255   if (log)
256     m_objfile.GetModule()->LogMessage(
257         log, "Reading compact unwind first-level indexes");
258
259   if (!m_unwindinfo_data_computed) {
260     if (m_section_sp->IsEncrypted()) {
261       // Can't get section contents of a protected/encrypted section until we
262       // have a live process and can read them out of memory.
263       if (process_sp.get() == nullptr)
264         return;
265       m_section_contents_if_encrypted =
266           std::make_shared<DataBufferHeap>(m_section_sp->GetByteSize(), 0);
267       Status error;
268       if (process_sp->ReadMemory(
269               m_section_sp->GetLoadBaseAddress(&process_sp->GetTarget()),
270               m_section_contents_if_encrypted->GetBytes(),
271               m_section_sp->GetByteSize(),
272               error) == m_section_sp->GetByteSize() &&
273           error.Success()) {
274         m_unwindinfo_data.SetAddressByteSize(
275             process_sp->GetTarget().GetArchitecture().GetAddressByteSize());
276         m_unwindinfo_data.SetByteOrder(
277             process_sp->GetTarget().GetArchitecture().GetByteOrder());
278         m_unwindinfo_data.SetData(m_section_contents_if_encrypted, 0);
279       }
280     } else {
281       m_objfile.ReadSectionData(m_section_sp.get(), m_unwindinfo_data);
282     }
283     if (m_unwindinfo_data.GetByteSize() != m_section_sp->GetByteSize())
284       return;
285     m_unwindinfo_data_computed = true;
286   }
287
288   if (m_unwindinfo_data.GetByteSize() > 0) {
289     offset_t offset = 0;
290
291     // struct unwind_info_section_header
292     // {
293     // uint32_t    version;            // UNWIND_SECTION_VERSION
294     // uint32_t    commonEncodingsArraySectionOffset;
295     // uint32_t    commonEncodingsArrayCount;
296     // uint32_t    personalityArraySectionOffset;
297     // uint32_t    personalityArrayCount;
298     // uint32_t    indexSectionOffset;
299     // uint32_t    indexCount;
300
301     m_unwind_header.version = m_unwindinfo_data.GetU32(&offset);
302     m_unwind_header.common_encodings_array_offset =
303         m_unwindinfo_data.GetU32(&offset);
304     m_unwind_header.common_encodings_array_count =
305         m_unwindinfo_data.GetU32(&offset);
306     m_unwind_header.personality_array_offset =
307         m_unwindinfo_data.GetU32(&offset);
308     m_unwind_header.personality_array_count = m_unwindinfo_data.GetU32(&offset);
309     uint32_t indexSectionOffset = m_unwindinfo_data.GetU32(&offset);
310
311     uint32_t indexCount = m_unwindinfo_data.GetU32(&offset);
312
313     if (m_unwind_header.common_encodings_array_offset >
314             m_unwindinfo_data.GetByteSize() ||
315         m_unwind_header.personality_array_offset >
316             m_unwindinfo_data.GetByteSize() ||
317         indexSectionOffset > m_unwindinfo_data.GetByteSize() ||
318         offset > m_unwindinfo_data.GetByteSize()) {
319       Host::SystemLog(Host::eSystemLogError, "error: Invalid offset "
320                                              "encountered in compact unwind "
321                                              "info, skipping\n");
322       // don't trust anything from this compact_unwind section if it looks
323       // blatantly invalid data in the header.
324       m_indexes_computed = eLazyBoolNo;
325       return;
326     }
327
328     // Parse the basic information from the indexes We wait to scan the second
329     // level page info until it's needed
330
331     // struct unwind_info_section_header_index_entry {
332     //     uint32_t        functionOffset;
333     //     uint32_t        secondLevelPagesSectionOffset;
334     //     uint32_t        lsdaIndexArraySectionOffset;
335     // };
336
337     bool clear_address_zeroth_bit = false;
338     if (ArchSpec arch = m_objfile.GetArchitecture()) {
339       if (arch.GetTriple().getArch() == llvm::Triple::arm ||
340           arch.GetTriple().getArch() == llvm::Triple::thumb)
341         clear_address_zeroth_bit = true;
342     }
343
344     offset = indexSectionOffset;
345     for (uint32_t idx = 0; idx < indexCount; idx++) {
346       uint32_t function_offset =
347           m_unwindinfo_data.GetU32(&offset); // functionOffset
348       uint32_t second_level_offset =
349           m_unwindinfo_data.GetU32(&offset); // secondLevelPagesSectionOffset
350       uint32_t lsda_offset =
351           m_unwindinfo_data.GetU32(&offset); // lsdaIndexArraySectionOffset
352
353       if (second_level_offset > m_section_sp->GetByteSize() ||
354           lsda_offset > m_section_sp->GetByteSize()) {
355         m_indexes_computed = eLazyBoolNo;
356       }
357
358       if (clear_address_zeroth_bit)
359         function_offset &= ~1ull;
360
361       UnwindIndex this_index;
362       this_index.function_offset = function_offset;
363       this_index.second_level = second_level_offset;
364       this_index.lsda_array_start = lsda_offset;
365
366       if (m_indexes.size() > 0) {
367         m_indexes[m_indexes.size() - 1].lsda_array_end = lsda_offset;
368       }
369
370       if (second_level_offset == 0) {
371         this_index.sentinal_entry = true;
372       }
373
374       m_indexes.push_back(this_index);
375     }
376     m_indexes_computed = eLazyBoolYes;
377   } else {
378     m_indexes_computed = eLazyBoolNo;
379   }
380 }
381
382 uint32_t CompactUnwindInfo::GetLSDAForFunctionOffset(uint32_t lsda_offset,
383                                                      uint32_t lsda_count,
384                                                      uint32_t function_offset) {
385   // struct unwind_info_section_header_lsda_index_entry {
386   //         uint32_t        functionOffset;
387   //         uint32_t        lsdaOffset;
388   // };
389
390   offset_t first_entry = lsda_offset;
391   uint32_t low = 0;
392   uint32_t high = lsda_count;
393   while (low < high) {
394     uint32_t mid = (low + high) / 2;
395     offset_t offset = first_entry + (mid * 8);
396     uint32_t mid_func_offset =
397         m_unwindinfo_data.GetU32(&offset); // functionOffset
398     uint32_t mid_lsda_offset = m_unwindinfo_data.GetU32(&offset); // lsdaOffset
399     if (mid_func_offset == function_offset) {
400       return mid_lsda_offset;
401     }
402     if (mid_func_offset < function_offset) {
403       low = mid + 1;
404     } else {
405       high = mid;
406     }
407   }
408   return 0;
409 }
410
411 lldb::offset_t CompactUnwindInfo::BinarySearchRegularSecondPage(
412     uint32_t entry_page_offset, uint32_t entry_count, uint32_t function_offset,
413     uint32_t *entry_func_start_offset, uint32_t *entry_func_end_offset) {
414   // typedef uint32_t compact_unwind_encoding_t;
415   // struct unwind_info_regular_second_level_entry {
416   //     uint32_t                    functionOffset;
417   //     compact_unwind_encoding_t    encoding;
418
419   offset_t first_entry = entry_page_offset;
420
421   uint32_t low = 0;
422   uint32_t high = entry_count;
423   uint32_t last = high - 1;
424   while (low < high) {
425     uint32_t mid = (low + high) / 2;
426     offset_t offset = first_entry + (mid * 8);
427     uint32_t mid_func_offset =
428         m_unwindinfo_data.GetU32(&offset); // functionOffset
429     uint32_t next_func_offset = 0;
430     if (mid < last) {
431       offset = first_entry + ((mid + 1) * 8);
432       next_func_offset = m_unwindinfo_data.GetU32(&offset); // functionOffset
433     }
434     if (mid_func_offset <= function_offset) {
435       if (mid == last || (next_func_offset > function_offset)) {
436         if (entry_func_start_offset)
437           *entry_func_start_offset = mid_func_offset;
438         if (mid != last && entry_func_end_offset)
439           *entry_func_end_offset = next_func_offset;
440         return first_entry + (mid * 8);
441       } else {
442         low = mid + 1;
443       }
444     } else {
445       high = mid;
446     }
447   }
448   return LLDB_INVALID_OFFSET;
449 }
450
451 uint32_t CompactUnwindInfo::BinarySearchCompressedSecondPage(
452     uint32_t entry_page_offset, uint32_t entry_count,
453     uint32_t function_offset_to_find, uint32_t function_offset_base,
454     uint32_t *entry_func_start_offset, uint32_t *entry_func_end_offset) {
455   offset_t first_entry = entry_page_offset;
456
457   uint32_t low = 0;
458   uint32_t high = entry_count;
459   uint32_t last = high - 1;
460   while (low < high) {
461     uint32_t mid = (low + high) / 2;
462     offset_t offset = first_entry + (mid * 4);
463     uint32_t entry = m_unwindinfo_data.GetU32(&offset); // entry
464     uint32_t mid_func_offset = UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET(entry);
465     mid_func_offset += function_offset_base;
466     uint32_t next_func_offset = 0;
467     if (mid < last) {
468       offset = first_entry + ((mid + 1) * 4);
469       uint32_t next_entry = m_unwindinfo_data.GetU32(&offset); // entry
470       next_func_offset = UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET(next_entry);
471       next_func_offset += function_offset_base;
472     }
473     if (mid_func_offset <= function_offset_to_find) {
474       if (mid == last || (next_func_offset > function_offset_to_find)) {
475         if (entry_func_start_offset)
476           *entry_func_start_offset = mid_func_offset;
477         if (mid != last && entry_func_end_offset)
478           *entry_func_end_offset = next_func_offset;
479         return UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX(entry);
480       } else {
481         low = mid + 1;
482       }
483     } else {
484       high = mid;
485     }
486   }
487
488   return UINT32_MAX;
489 }
490
491 bool CompactUnwindInfo::GetCompactUnwindInfoForFunction(
492     Target &target, Address address, FunctionInfo &unwind_info) {
493   unwind_info.encoding = 0;
494   unwind_info.lsda_address.Clear();
495   unwind_info.personality_ptr_address.Clear();
496
497   if (!IsValid(target.GetProcessSP()))
498     return false;
499
500   addr_t text_section_file_address = LLDB_INVALID_ADDRESS;
501   SectionList *sl = m_objfile.GetSectionList();
502   if (sl) {
503     SectionSP text_sect = sl->FindSectionByType(eSectionTypeCode, true);
504     if (text_sect.get()) {
505       text_section_file_address = text_sect->GetFileAddress();
506     }
507   }
508   if (text_section_file_address == LLDB_INVALID_ADDRESS)
509     return false;
510
511   addr_t function_offset =
512       address.GetFileAddress() - m_objfile.GetBaseAddress().GetFileAddress();
513
514   UnwindIndex key;
515   key.function_offset = function_offset;
516
517   std::vector<UnwindIndex>::const_iterator it;
518   it = std::lower_bound(m_indexes.begin(), m_indexes.end(), key);
519   if (it == m_indexes.end()) {
520     return false;
521   }
522
523   if (it->function_offset != key.function_offset) {
524     if (it != m_indexes.begin())
525       --it;
526   }
527
528   if (it->sentinal_entry) {
529     return false;
530   }
531
532   auto next_it = it + 1;
533   if (next_it != m_indexes.end()) {
534     // initialize the function offset end range to be the start of the next
535     // index offset.  If we find an entry which is at the end of the index
536     // table, this will establish the range end.
537     unwind_info.valid_range_offset_end = next_it->function_offset;
538   }
539
540   offset_t second_page_offset = it->second_level;
541   offset_t lsda_array_start = it->lsda_array_start;
542   offset_t lsda_array_count = (it->lsda_array_end - it->lsda_array_start) / 8;
543
544   offset_t offset = second_page_offset;
545   uint32_t kind = m_unwindinfo_data.GetU32(
546       &offset); // UNWIND_SECOND_LEVEL_REGULAR or UNWIND_SECOND_LEVEL_COMPRESSED
547
548   if (kind == UNWIND_SECOND_LEVEL_REGULAR) {
549     // struct unwind_info_regular_second_level_page_header {
550     //     uint32_t    kind;    // UNWIND_SECOND_LEVEL_REGULAR
551     //     uint16_t    entryPageOffset;
552     //     uint16_t    entryCount;
553
554     // typedef uint32_t compact_unwind_encoding_t;
555     // struct unwind_info_regular_second_level_entry {
556     //     uint32_t                    functionOffset;
557     //     compact_unwind_encoding_t    encoding;
558
559     uint16_t entry_page_offset =
560         m_unwindinfo_data.GetU16(&offset);                    // entryPageOffset
561     uint16_t entry_count = m_unwindinfo_data.GetU16(&offset); // entryCount
562
563     offset_t entry_offset = BinarySearchRegularSecondPage(
564         second_page_offset + entry_page_offset, entry_count, function_offset,
565         &unwind_info.valid_range_offset_start,
566         &unwind_info.valid_range_offset_end);
567     if (entry_offset == LLDB_INVALID_OFFSET) {
568       return false;
569     }
570     entry_offset += 4; // skip over functionOffset
571     unwind_info.encoding = m_unwindinfo_data.GetU32(&entry_offset); // encoding
572     if (unwind_info.encoding & UNWIND_HAS_LSDA) {
573       SectionList *sl = m_objfile.GetSectionList();
574       if (sl) {
575         uint32_t lsda_offset = GetLSDAForFunctionOffset(
576             lsda_array_start, lsda_array_count, function_offset);
577         addr_t objfile_base_address =
578             m_objfile.GetBaseAddress().GetFileAddress();
579         unwind_info.lsda_address.ResolveAddressUsingFileSections(
580             objfile_base_address + lsda_offset, sl);
581       }
582     }
583     if (unwind_info.encoding & UNWIND_PERSONALITY_MASK) {
584       uint32_t personality_index =
585           EXTRACT_BITS(unwind_info.encoding, UNWIND_PERSONALITY_MASK);
586
587       if (personality_index > 0) {
588         personality_index--;
589         if (personality_index < m_unwind_header.personality_array_count) {
590           offset_t offset = m_unwind_header.personality_array_offset;
591           offset += 4 * personality_index;
592           SectionList *sl = m_objfile.GetSectionList();
593           if (sl) {
594             uint32_t personality_offset = m_unwindinfo_data.GetU32(&offset);
595             addr_t objfile_base_address =
596                 m_objfile.GetBaseAddress().GetFileAddress();
597             unwind_info.personality_ptr_address.ResolveAddressUsingFileSections(
598                 objfile_base_address + personality_offset, sl);
599           }
600         }
601       }
602     }
603     return true;
604   } else if (kind == UNWIND_SECOND_LEVEL_COMPRESSED) {
605     // struct unwind_info_compressed_second_level_page_header {
606     //     uint32_t    kind;    // UNWIND_SECOND_LEVEL_COMPRESSED
607     //     uint16_t    entryPageOffset;         // offset from this 2nd lvl page
608     //     idx to array of entries
609     //                                          // (an entry has a function
610     //                                          offset and index into the
611     //                                          encodings)
612     //                                          // NB function offset from the
613     //                                          entry in the compressed page
614     //                                          // must be added to the index's
615     //                                          functionOffset value.
616     //     uint16_t    entryCount;
617     //     uint16_t    encodingsPageOffset;     // offset from this 2nd lvl page
618     //     idx to array of encodings
619     //     uint16_t    encodingsCount;
620
621     uint16_t entry_page_offset =
622         m_unwindinfo_data.GetU16(&offset);                    // entryPageOffset
623     uint16_t entry_count = m_unwindinfo_data.GetU16(&offset); // entryCount
624     uint16_t encodings_page_offset =
625         m_unwindinfo_data.GetU16(&offset); // encodingsPageOffset
626     uint16_t encodings_count =
627         m_unwindinfo_data.GetU16(&offset); // encodingsCount
628
629     uint32_t encoding_index = BinarySearchCompressedSecondPage(
630         second_page_offset + entry_page_offset, entry_count, function_offset,
631         it->function_offset, &unwind_info.valid_range_offset_start,
632         &unwind_info.valid_range_offset_end);
633     if (encoding_index == UINT32_MAX ||
634         encoding_index >=
635             encodings_count + m_unwind_header.common_encodings_array_count) {
636       return false;
637     }
638     uint32_t encoding = 0;
639     if (encoding_index < m_unwind_header.common_encodings_array_count) {
640       offset = m_unwind_header.common_encodings_array_offset +
641                (encoding_index * sizeof(uint32_t));
642       encoding = m_unwindinfo_data.GetU32(
643           &offset); // encoding entry from the commonEncodingsArray
644     } else {
645       uint32_t page_specific_entry_index =
646           encoding_index - m_unwind_header.common_encodings_array_count;
647       offset = second_page_offset + encodings_page_offset +
648                (page_specific_entry_index * sizeof(uint32_t));
649       encoding = m_unwindinfo_data.GetU32(
650           &offset); // encoding entry from the page-specific encoding array
651     }
652     if (encoding == 0)
653       return false;
654
655     unwind_info.encoding = encoding;
656     if (unwind_info.encoding & UNWIND_HAS_LSDA) {
657       SectionList *sl = m_objfile.GetSectionList();
658       if (sl) {
659         uint32_t lsda_offset = GetLSDAForFunctionOffset(
660             lsda_array_start, lsda_array_count, function_offset);
661         addr_t objfile_base_address =
662             m_objfile.GetBaseAddress().GetFileAddress();
663         unwind_info.lsda_address.ResolveAddressUsingFileSections(
664             objfile_base_address + lsda_offset, sl);
665       }
666     }
667     if (unwind_info.encoding & UNWIND_PERSONALITY_MASK) {
668       uint32_t personality_index =
669           EXTRACT_BITS(unwind_info.encoding, UNWIND_PERSONALITY_MASK);
670
671       if (personality_index > 0) {
672         personality_index--;
673         if (personality_index < m_unwind_header.personality_array_count) {
674           offset_t offset = m_unwind_header.personality_array_offset;
675           offset += 4 * personality_index;
676           SectionList *sl = m_objfile.GetSectionList();
677           if (sl) {
678             uint32_t personality_offset = m_unwindinfo_data.GetU32(&offset);
679             addr_t objfile_base_address =
680                 m_objfile.GetBaseAddress().GetFileAddress();
681             unwind_info.personality_ptr_address.ResolveAddressUsingFileSections(
682                 objfile_base_address + personality_offset, sl);
683           }
684         }
685       }
686     }
687     return true;
688   }
689   return false;
690 }
691
692 enum x86_64_eh_regnum {
693   rax = 0,
694   rdx = 1,
695   rcx = 2,
696   rbx = 3,
697   rsi = 4,
698   rdi = 5,
699   rbp = 6,
700   rsp = 7,
701   r8 = 8,
702   r9 = 9,
703   r10 = 10,
704   r11 = 11,
705   r12 = 12,
706   r13 = 13,
707   r14 = 14,
708   r15 = 15,
709   rip = 16 // this is officially the Return Address register number, but close
710            // enough
711 };
712
713 // Convert the compact_unwind_info.h register numbering scheme to
714 // eRegisterKindEHFrame (eh_frame) register numbering scheme.
715 uint32_t translate_to_eh_frame_regnum_x86_64(uint32_t unwind_regno) {
716   switch (unwind_regno) {
717   case UNWIND_X86_64_REG_RBX:
718     return x86_64_eh_regnum::rbx;
719   case UNWIND_X86_64_REG_R12:
720     return x86_64_eh_regnum::r12;
721   case UNWIND_X86_64_REG_R13:
722     return x86_64_eh_regnum::r13;
723   case UNWIND_X86_64_REG_R14:
724     return x86_64_eh_regnum::r14;
725   case UNWIND_X86_64_REG_R15:
726     return x86_64_eh_regnum::r15;
727   case UNWIND_X86_64_REG_RBP:
728     return x86_64_eh_regnum::rbp;
729   default:
730     return LLDB_INVALID_REGNUM;
731   }
732 }
733
734 bool CompactUnwindInfo::CreateUnwindPlan_x86_64(Target &target,
735                                                 FunctionInfo &function_info,
736                                                 UnwindPlan &unwind_plan,
737                                                 Address pc_or_function_start) {
738   unwind_plan.SetSourceName("compact unwind info");
739   unwind_plan.SetSourcedFromCompiler(eLazyBoolYes);
740   unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
741   unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo);
742   unwind_plan.SetRegisterKind(eRegisterKindEHFrame);
743
744   unwind_plan.SetLSDAAddress(function_info.lsda_address);
745   unwind_plan.SetPersonalityFunctionPtr(function_info.personality_ptr_address);
746
747   UnwindPlan::RowSP row(new UnwindPlan::Row);
748
749   const int wordsize = 8;
750   int mode = function_info.encoding & UNWIND_X86_64_MODE_MASK;
751   switch (mode) {
752   case UNWIND_X86_64_MODE_RBP_FRAME: {
753     row->GetCFAValue().SetIsRegisterPlusOffset(
754         translate_to_eh_frame_regnum_x86_64(UNWIND_X86_64_REG_RBP),
755         2 * wordsize);
756     row->SetOffset(0);
757     row->SetRegisterLocationToAtCFAPlusOffset(x86_64_eh_regnum::rbp,
758                                               wordsize * -2, true);
759     row->SetRegisterLocationToAtCFAPlusOffset(x86_64_eh_regnum::rip,
760                                               wordsize * -1, true);
761     row->SetRegisterLocationToIsCFAPlusOffset(x86_64_eh_regnum::rsp, 0, true);
762
763     uint32_t saved_registers_offset =
764         EXTRACT_BITS(function_info.encoding, UNWIND_X86_64_RBP_FRAME_OFFSET);
765
766     uint32_t saved_registers_locations =
767         EXTRACT_BITS(function_info.encoding, UNWIND_X86_64_RBP_FRAME_REGISTERS);
768
769     saved_registers_offset += 2;
770
771     for (int i = 0; i < 5; i++) {
772       uint32_t regnum = saved_registers_locations & 0x7;
773       switch (regnum) {
774       case UNWIND_X86_64_REG_NONE:
775         break;
776       case UNWIND_X86_64_REG_RBX:
777       case UNWIND_X86_64_REG_R12:
778       case UNWIND_X86_64_REG_R13:
779       case UNWIND_X86_64_REG_R14:
780       case UNWIND_X86_64_REG_R15:
781         row->SetRegisterLocationToAtCFAPlusOffset(
782             translate_to_eh_frame_regnum_x86_64(regnum),
783             wordsize * -saved_registers_offset, true);
784         break;
785       }
786       saved_registers_offset--;
787       saved_registers_locations >>= 3;
788     }
789     unwind_plan.AppendRow(row);
790     return true;
791   } break;
792
793   case UNWIND_X86_64_MODE_STACK_IND: {
794     // The clang in Xcode 6 is emitting incorrect compact unwind encodings for
795     // this style of unwind.  It was fixed in llvm r217020. The clang in Xcode
796     // 7 has this fixed.
797     return false;
798   } break;
799
800   case UNWIND_X86_64_MODE_STACK_IMMD: {
801     uint32_t stack_size = EXTRACT_BITS(function_info.encoding,
802                                        UNWIND_X86_64_FRAMELESS_STACK_SIZE);
803     uint32_t register_count = EXTRACT_BITS(
804         function_info.encoding, UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT);
805     uint32_t permutation = EXTRACT_BITS(
806         function_info.encoding, UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION);
807
808     if (mode == UNWIND_X86_64_MODE_STACK_IND &&
809         function_info.valid_range_offset_start != 0) {
810       uint32_t stack_adjust = EXTRACT_BITS(
811           function_info.encoding, UNWIND_X86_64_FRAMELESS_STACK_ADJUST);
812
813       // offset into the function instructions; 0 == beginning of first
814       // instruction
815       uint32_t offset_to_subl_insn = EXTRACT_BITS(
816           function_info.encoding, UNWIND_X86_64_FRAMELESS_STACK_SIZE);
817
818       SectionList *sl = m_objfile.GetSectionList();
819       if (sl) {
820         ProcessSP process_sp = target.GetProcessSP();
821         if (process_sp) {
822           Address subl_payload_addr(function_info.valid_range_offset_start, sl);
823           subl_payload_addr.Slide(offset_to_subl_insn);
824           Status error;
825           uint64_t large_stack_size = process_sp->ReadUnsignedIntegerFromMemory(
826               subl_payload_addr.GetLoadAddress(&target), 4, 0, error);
827           if (large_stack_size != 0 && error.Success()) {
828             // Got the large stack frame size correctly - use it
829             stack_size = large_stack_size + (stack_adjust * wordsize);
830           } else {
831             return false;
832           }
833         } else {
834           return false;
835         }
836       } else {
837         return false;
838       }
839     }
840
841     int32_t offset = mode == UNWIND_X86_64_MODE_STACK_IND
842                          ? stack_size
843                          : stack_size * wordsize;
844     row->GetCFAValue().SetIsRegisterPlusOffset(x86_64_eh_regnum::rsp, offset);
845
846     row->SetOffset(0);
847     row->SetRegisterLocationToAtCFAPlusOffset(x86_64_eh_regnum::rip,
848                                               wordsize * -1, true);
849     row->SetRegisterLocationToIsCFAPlusOffset(x86_64_eh_regnum::rsp, 0, true);
850
851     if (register_count > 0) {
852
853       // We need to include (up to) 6 registers in 10 bits. That would be 18
854       // bits if we just used 3 bits per reg to indicate the order they're
855       // saved on the stack.
856       //
857       // This is done with Lehmer code permutation, e.g. see
858       // http://stackoverflow.com/questions/1506078/fast-permutation-number-
859       // permutation-mapping-algorithms
860       int permunreg[6] = {0, 0, 0, 0, 0, 0};
861
862       // This decodes the variable-base number in the 10 bits and gives us the
863       // Lehmer code sequence which can then be decoded.
864
865       switch (register_count) {
866       case 6:
867         permunreg[0] = permutation / 120; // 120 == 5!
868         permutation -= (permunreg[0] * 120);
869         permunreg[1] = permutation / 24; // 24 == 4!
870         permutation -= (permunreg[1] * 24);
871         permunreg[2] = permutation / 6; // 6 == 3!
872         permutation -= (permunreg[2] * 6);
873         permunreg[3] = permutation / 2; // 2 == 2!
874         permutation -= (permunreg[3] * 2);
875         permunreg[4] = permutation; // 1 == 1!
876         permunreg[5] = 0;
877         break;
878       case 5:
879         permunreg[0] = permutation / 120;
880         permutation -= (permunreg[0] * 120);
881         permunreg[1] = permutation / 24;
882         permutation -= (permunreg[1] * 24);
883         permunreg[2] = permutation / 6;
884         permutation -= (permunreg[2] * 6);
885         permunreg[3] = permutation / 2;
886         permutation -= (permunreg[3] * 2);
887         permunreg[4] = permutation;
888         break;
889       case 4:
890         permunreg[0] = permutation / 60;
891         permutation -= (permunreg[0] * 60);
892         permunreg[1] = permutation / 12;
893         permutation -= (permunreg[1] * 12);
894         permunreg[2] = permutation / 3;
895         permutation -= (permunreg[2] * 3);
896         permunreg[3] = permutation;
897         break;
898       case 3:
899         permunreg[0] = permutation / 20;
900         permutation -= (permunreg[0] * 20);
901         permunreg[1] = permutation / 4;
902         permutation -= (permunreg[1] * 4);
903         permunreg[2] = permutation;
904         break;
905       case 2:
906         permunreg[0] = permutation / 5;
907         permutation -= (permunreg[0] * 5);
908         permunreg[1] = permutation;
909         break;
910       case 1:
911         permunreg[0] = permutation;
912         break;
913       }
914
915       // Decode the Lehmer code for this permutation of the registers v.
916       // http://en.wikipedia.org/wiki/Lehmer_code
917
918       int registers[6] = {UNWIND_X86_64_REG_NONE, UNWIND_X86_64_REG_NONE,
919                           UNWIND_X86_64_REG_NONE, UNWIND_X86_64_REG_NONE,
920                           UNWIND_X86_64_REG_NONE, UNWIND_X86_64_REG_NONE};
921       bool used[7] = {false, false, false, false, false, false, false};
922       for (uint32_t i = 0; i < register_count; i++) {
923         int renum = 0;
924         for (int j = 1; j < 7; j++) {
925           if (!used[j]) {
926             if (renum == permunreg[i]) {
927               registers[i] = j;
928               used[j] = true;
929               break;
930             }
931             renum++;
932           }
933         }
934       }
935
936       uint32_t saved_registers_offset = 1;
937       saved_registers_offset++;
938
939       for (int i = (sizeof(registers) / sizeof(int)) - 1; i >= 0; i--) {
940         switch (registers[i]) {
941         case UNWIND_X86_64_REG_NONE:
942           break;
943         case UNWIND_X86_64_REG_RBX:
944         case UNWIND_X86_64_REG_R12:
945         case UNWIND_X86_64_REG_R13:
946         case UNWIND_X86_64_REG_R14:
947         case UNWIND_X86_64_REG_R15:
948         case UNWIND_X86_64_REG_RBP:
949           row->SetRegisterLocationToAtCFAPlusOffset(
950               translate_to_eh_frame_regnum_x86_64(registers[i]),
951               wordsize * -saved_registers_offset, true);
952           saved_registers_offset++;
953           break;
954         }
955       }
956     }
957     unwind_plan.AppendRow(row);
958     return true;
959   } break;
960
961   case UNWIND_X86_64_MODE_DWARF: {
962     return false;
963   } break;
964
965   case 0: {
966     return false;
967   } break;
968   }
969   return false;
970 }
971
972 enum i386_eh_regnum {
973   eax = 0,
974   ecx = 1,
975   edx = 2,
976   ebx = 3,
977   ebp = 4,
978   esp = 5,
979   esi = 6,
980   edi = 7,
981   eip = 8 // this is officially the Return Address register number, but close
982           // enough
983 };
984
985 // Convert the compact_unwind_info.h register numbering scheme to
986 // eRegisterKindEHFrame (eh_frame) register numbering scheme.
987 uint32_t translate_to_eh_frame_regnum_i386(uint32_t unwind_regno) {
988   switch (unwind_regno) {
989   case UNWIND_X86_REG_EBX:
990     return i386_eh_regnum::ebx;
991   case UNWIND_X86_REG_ECX:
992     return i386_eh_regnum::ecx;
993   case UNWIND_X86_REG_EDX:
994     return i386_eh_regnum::edx;
995   case UNWIND_X86_REG_EDI:
996     return i386_eh_regnum::edi;
997   case UNWIND_X86_REG_ESI:
998     return i386_eh_regnum::esi;
999   case UNWIND_X86_REG_EBP:
1000     return i386_eh_regnum::ebp;
1001   default:
1002     return LLDB_INVALID_REGNUM;
1003   }
1004 }
1005
1006 bool CompactUnwindInfo::CreateUnwindPlan_i386(Target &target,
1007                                               FunctionInfo &function_info,
1008                                               UnwindPlan &unwind_plan,
1009                                               Address pc_or_function_start) {
1010   unwind_plan.SetSourceName("compact unwind info");
1011   unwind_plan.SetSourcedFromCompiler(eLazyBoolYes);
1012   unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
1013   unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo);
1014   unwind_plan.SetRegisterKind(eRegisterKindEHFrame);
1015
1016   unwind_plan.SetLSDAAddress(function_info.lsda_address);
1017   unwind_plan.SetPersonalityFunctionPtr(function_info.personality_ptr_address);
1018
1019   UnwindPlan::RowSP row(new UnwindPlan::Row);
1020
1021   const int wordsize = 4;
1022   int mode = function_info.encoding & UNWIND_X86_MODE_MASK;
1023   switch (mode) {
1024   case UNWIND_X86_MODE_EBP_FRAME: {
1025     row->GetCFAValue().SetIsRegisterPlusOffset(
1026         translate_to_eh_frame_regnum_i386(UNWIND_X86_REG_EBP), 2 * wordsize);
1027     row->SetOffset(0);
1028     row->SetRegisterLocationToAtCFAPlusOffset(i386_eh_regnum::ebp,
1029                                               wordsize * -2, true);
1030     row->SetRegisterLocationToAtCFAPlusOffset(i386_eh_regnum::eip,
1031                                               wordsize * -1, true);
1032     row->SetRegisterLocationToIsCFAPlusOffset(i386_eh_regnum::esp, 0, true);
1033
1034     uint32_t saved_registers_offset =
1035         EXTRACT_BITS(function_info.encoding, UNWIND_X86_EBP_FRAME_OFFSET);
1036
1037     uint32_t saved_registers_locations =
1038         EXTRACT_BITS(function_info.encoding, UNWIND_X86_EBP_FRAME_REGISTERS);
1039
1040     saved_registers_offset += 2;
1041
1042     for (int i = 0; i < 5; i++) {
1043       uint32_t regnum = saved_registers_locations & 0x7;
1044       switch (regnum) {
1045       case UNWIND_X86_REG_NONE:
1046         break;
1047       case UNWIND_X86_REG_EBX:
1048       case UNWIND_X86_REG_ECX:
1049       case UNWIND_X86_REG_EDX:
1050       case UNWIND_X86_REG_EDI:
1051       case UNWIND_X86_REG_ESI:
1052         row->SetRegisterLocationToAtCFAPlusOffset(
1053             translate_to_eh_frame_regnum_i386(regnum),
1054             wordsize * -saved_registers_offset, true);
1055         break;
1056       }
1057       saved_registers_offset--;
1058       saved_registers_locations >>= 3;
1059     }
1060     unwind_plan.AppendRow(row);
1061     return true;
1062   } break;
1063
1064   case UNWIND_X86_MODE_STACK_IND:
1065   case UNWIND_X86_MODE_STACK_IMMD: {
1066     uint32_t stack_size =
1067         EXTRACT_BITS(function_info.encoding, UNWIND_X86_FRAMELESS_STACK_SIZE);
1068     uint32_t register_count = EXTRACT_BITS(
1069         function_info.encoding, UNWIND_X86_FRAMELESS_STACK_REG_COUNT);
1070     uint32_t permutation = EXTRACT_BITS(
1071         function_info.encoding, UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION);
1072
1073     if (mode == UNWIND_X86_MODE_STACK_IND &&
1074         function_info.valid_range_offset_start != 0) {
1075       uint32_t stack_adjust = EXTRACT_BITS(function_info.encoding,
1076                                            UNWIND_X86_FRAMELESS_STACK_ADJUST);
1077
1078       // offset into the function instructions; 0 == beginning of first
1079       // instruction
1080       uint32_t offset_to_subl_insn =
1081           EXTRACT_BITS(function_info.encoding, UNWIND_X86_FRAMELESS_STACK_SIZE);
1082
1083       SectionList *sl = m_objfile.GetSectionList();
1084       if (sl) {
1085         ProcessSP process_sp = target.GetProcessSP();
1086         if (process_sp) {
1087           Address subl_payload_addr(function_info.valid_range_offset_start, sl);
1088           subl_payload_addr.Slide(offset_to_subl_insn);
1089           Status error;
1090           uint64_t large_stack_size = process_sp->ReadUnsignedIntegerFromMemory(
1091               subl_payload_addr.GetLoadAddress(&target), 4, 0, error);
1092           if (large_stack_size != 0 && error.Success()) {
1093             // Got the large stack frame size correctly - use it
1094             stack_size = large_stack_size + (stack_adjust * wordsize);
1095           } else {
1096             return false;
1097           }
1098         } else {
1099           return false;
1100         }
1101       } else {
1102         return false;
1103       }
1104     }
1105
1106     int32_t offset =
1107         mode == UNWIND_X86_MODE_STACK_IND ? stack_size : stack_size * wordsize;
1108     row->GetCFAValue().SetIsRegisterPlusOffset(i386_eh_regnum::esp, offset);
1109     row->SetOffset(0);
1110     row->SetRegisterLocationToAtCFAPlusOffset(i386_eh_regnum::eip,
1111                                               wordsize * -1, true);
1112     row->SetRegisterLocationToIsCFAPlusOffset(i386_eh_regnum::esp, 0, true);
1113
1114     if (register_count > 0) {
1115
1116       // We need to include (up to) 6 registers in 10 bits. That would be 18
1117       // bits if we just used 3 bits per reg to indicate the order they're
1118       // saved on the stack.
1119       //
1120       // This is done with Lehmer code permutation, e.g. see
1121       // http://stackoverflow.com/questions/1506078/fast-permutation-number-
1122       // permutation-mapping-algorithms
1123       int permunreg[6] = {0, 0, 0, 0, 0, 0};
1124
1125       // This decodes the variable-base number in the 10 bits and gives us the
1126       // Lehmer code sequence which can then be decoded.
1127
1128       switch (register_count) {
1129       case 6:
1130         permunreg[0] = permutation / 120; // 120 == 5!
1131         permutation -= (permunreg[0] * 120);
1132         permunreg[1] = permutation / 24; // 24 == 4!
1133         permutation -= (permunreg[1] * 24);
1134         permunreg[2] = permutation / 6; // 6 == 3!
1135         permutation -= (permunreg[2] * 6);
1136         permunreg[3] = permutation / 2; // 2 == 2!
1137         permutation -= (permunreg[3] * 2);
1138         permunreg[4] = permutation; // 1 == 1!
1139         permunreg[5] = 0;
1140         break;
1141       case 5:
1142         permunreg[0] = permutation / 120;
1143         permutation -= (permunreg[0] * 120);
1144         permunreg[1] = permutation / 24;
1145         permutation -= (permunreg[1] * 24);
1146         permunreg[2] = permutation / 6;
1147         permutation -= (permunreg[2] * 6);
1148         permunreg[3] = permutation / 2;
1149         permutation -= (permunreg[3] * 2);
1150         permunreg[4] = permutation;
1151         break;
1152       case 4:
1153         permunreg[0] = permutation / 60;
1154         permutation -= (permunreg[0] * 60);
1155         permunreg[1] = permutation / 12;
1156         permutation -= (permunreg[1] * 12);
1157         permunreg[2] = permutation / 3;
1158         permutation -= (permunreg[2] * 3);
1159         permunreg[3] = permutation;
1160         break;
1161       case 3:
1162         permunreg[0] = permutation / 20;
1163         permutation -= (permunreg[0] * 20);
1164         permunreg[1] = permutation / 4;
1165         permutation -= (permunreg[1] * 4);
1166         permunreg[2] = permutation;
1167         break;
1168       case 2:
1169         permunreg[0] = permutation / 5;
1170         permutation -= (permunreg[0] * 5);
1171         permunreg[1] = permutation;
1172         break;
1173       case 1:
1174         permunreg[0] = permutation;
1175         break;
1176       }
1177
1178       // Decode the Lehmer code for this permutation of the registers v.
1179       // http://en.wikipedia.org/wiki/Lehmer_code
1180
1181       int registers[6] = {UNWIND_X86_REG_NONE, UNWIND_X86_REG_NONE,
1182                           UNWIND_X86_REG_NONE, UNWIND_X86_REG_NONE,
1183                           UNWIND_X86_REG_NONE, UNWIND_X86_REG_NONE};
1184       bool used[7] = {false, false, false, false, false, false, false};
1185       for (uint32_t i = 0; i < register_count; i++) {
1186         int renum = 0;
1187         for (int j = 1; j < 7; j++) {
1188           if (!used[j]) {
1189             if (renum == permunreg[i]) {
1190               registers[i] = j;
1191               used[j] = true;
1192               break;
1193             }
1194             renum++;
1195           }
1196         }
1197       }
1198
1199       uint32_t saved_registers_offset = 1;
1200       saved_registers_offset++;
1201
1202       for (int i = (sizeof(registers) / sizeof(int)) - 1; i >= 0; i--) {
1203         switch (registers[i]) {
1204         case UNWIND_X86_REG_NONE:
1205           break;
1206         case UNWIND_X86_REG_EBX:
1207         case UNWIND_X86_REG_ECX:
1208         case UNWIND_X86_REG_EDX:
1209         case UNWIND_X86_REG_EDI:
1210         case UNWIND_X86_REG_ESI:
1211         case UNWIND_X86_REG_EBP:
1212           row->SetRegisterLocationToAtCFAPlusOffset(
1213               translate_to_eh_frame_regnum_i386(registers[i]),
1214               wordsize * -saved_registers_offset, true);
1215           saved_registers_offset++;
1216           break;
1217         }
1218       }
1219     }
1220
1221     unwind_plan.AppendRow(row);
1222     return true;
1223   } break;
1224
1225   case UNWIND_X86_MODE_DWARF: {
1226     return false;
1227   } break;
1228   }
1229   return false;
1230 }
1231
1232 // DWARF register numbers from "DWARF for the ARM 64-bit Architecture (AArch64)"
1233 // doc by ARM
1234
1235 enum arm64_eh_regnum {
1236   x19 = 19,
1237   x20 = 20,
1238   x21 = 21,
1239   x22 = 22,
1240   x23 = 23,
1241   x24 = 24,
1242   x25 = 25,
1243   x26 = 26,
1244   x27 = 27,
1245   x28 = 28,
1246
1247   fp = 29,
1248   ra = 30,
1249   sp = 31,
1250   pc = 32,
1251
1252   // Compact unwind encodes d8-d15 but we don't have eh_frame / dwarf reg #'s
1253   // for the 64-bit fp regs.  Normally in DWARF it's context sensitive - so it
1254   // knows it is fetching a 32- or 64-bit quantity from reg v8 to indicate s0
1255   // or d0 - but the unwinder is operating at a lower level and we'd try to
1256   // fetch 128 bits if we were told that v8 were stored on the stack...
1257   v8 = 72,
1258   v9 = 73,
1259   v10 = 74,
1260   v11 = 75,
1261   v12 = 76,
1262   v13 = 77,
1263   v14 = 78,
1264   v15 = 79,
1265 };
1266
1267 enum arm_eh_regnum {
1268   arm_r0 = 0,
1269   arm_r1 = 1,
1270   arm_r2 = 2,
1271   arm_r3 = 3,
1272   arm_r4 = 4,
1273   arm_r5 = 5,
1274   arm_r6 = 6,
1275   arm_r7 = 7,
1276   arm_r8 = 8,
1277   arm_r9 = 9,
1278   arm_r10 = 10,
1279   arm_r11 = 11,
1280   arm_r12 = 12,
1281
1282   arm_sp = 13,
1283   arm_lr = 14,
1284   arm_pc = 15,
1285
1286   arm_d0 = 256,
1287   arm_d1 = 257,
1288   arm_d2 = 258,
1289   arm_d3 = 259,
1290   arm_d4 = 260,
1291   arm_d5 = 261,
1292   arm_d6 = 262,
1293   arm_d7 = 263,
1294   arm_d8 = 264,
1295   arm_d9 = 265,
1296   arm_d10 = 266,
1297   arm_d11 = 267,
1298   arm_d12 = 268,
1299   arm_d13 = 269,
1300   arm_d14 = 270,
1301 };
1302
1303 bool CompactUnwindInfo::CreateUnwindPlan_arm64(Target &target,
1304                                                FunctionInfo &function_info,
1305                                                UnwindPlan &unwind_plan,
1306                                                Address pc_or_function_start) {
1307   unwind_plan.SetSourceName("compact unwind info");
1308   unwind_plan.SetSourcedFromCompiler(eLazyBoolYes);
1309   unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
1310   unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo);
1311   unwind_plan.SetRegisterKind(eRegisterKindEHFrame);
1312
1313   unwind_plan.SetLSDAAddress(function_info.lsda_address);
1314   unwind_plan.SetPersonalityFunctionPtr(function_info.personality_ptr_address);
1315
1316   UnwindPlan::RowSP row(new UnwindPlan::Row);
1317
1318   const int wordsize = 8;
1319   int mode = function_info.encoding & UNWIND_ARM64_MODE_MASK;
1320
1321   if (mode == UNWIND_ARM64_MODE_DWARF)
1322     return false;
1323
1324   if (mode == UNWIND_ARM64_MODE_FRAMELESS) {
1325     row->SetOffset(0);
1326
1327     uint32_t stack_size =
1328         (EXTRACT_BITS(function_info.encoding,
1329                       UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK)) *
1330         16;
1331
1332     // Our previous Call Frame Address is the stack pointer plus the stack size
1333     row->GetCFAValue().SetIsRegisterPlusOffset(arm64_eh_regnum::sp, stack_size);
1334
1335     // Our previous PC is in the LR
1336     row->SetRegisterLocationToRegister(arm64_eh_regnum::pc, arm64_eh_regnum::ra,
1337                                        true);
1338
1339     unwind_plan.AppendRow(row);
1340     return true;
1341   }
1342
1343   // Should not be possible
1344   if (mode != UNWIND_ARM64_MODE_FRAME)
1345     return false;
1346
1347   // mode == UNWIND_ARM64_MODE_FRAME
1348
1349   row->GetCFAValue().SetIsRegisterPlusOffset(arm64_eh_regnum::fp, 2 * wordsize);
1350   row->SetOffset(0);
1351   row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::fp, wordsize * -2,
1352                                             true);
1353   row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::pc, wordsize * -1,
1354                                             true);
1355   row->SetRegisterLocationToIsCFAPlusOffset(arm64_eh_regnum::sp, 0, true);
1356
1357   int reg_pairs_saved_count = 1;
1358
1359   uint32_t saved_register_bits = function_info.encoding & 0xfff;
1360
1361   if (saved_register_bits & UNWIND_ARM64_FRAME_X19_X20_PAIR) {
1362     int cfa_offset = reg_pairs_saved_count * -2 * wordsize;
1363     cfa_offset -= wordsize;
1364     row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x19, cfa_offset,
1365                                               true);
1366     cfa_offset -= wordsize;
1367     row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x20, cfa_offset,
1368                                               true);
1369     reg_pairs_saved_count++;
1370   }
1371
1372   if (saved_register_bits & UNWIND_ARM64_FRAME_X21_X22_PAIR) {
1373     int cfa_offset = reg_pairs_saved_count * -2 * wordsize;
1374     cfa_offset -= wordsize;
1375     row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x21, cfa_offset,
1376                                               true);
1377     cfa_offset -= wordsize;
1378     row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x22, cfa_offset,
1379                                               true);
1380     reg_pairs_saved_count++;
1381   }
1382
1383   if (saved_register_bits & UNWIND_ARM64_FRAME_X23_X24_PAIR) {
1384     int cfa_offset = reg_pairs_saved_count * -2 * wordsize;
1385     cfa_offset -= wordsize;
1386     row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x23, cfa_offset,
1387                                               true);
1388     cfa_offset -= wordsize;
1389     row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x24, cfa_offset,
1390                                               true);
1391     reg_pairs_saved_count++;
1392   }
1393
1394   if (saved_register_bits & UNWIND_ARM64_FRAME_X25_X26_PAIR) {
1395     int cfa_offset = reg_pairs_saved_count * -2 * wordsize;
1396     cfa_offset -= wordsize;
1397     row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x25, cfa_offset,
1398                                               true);
1399     cfa_offset -= wordsize;
1400     row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x26, cfa_offset,
1401                                               true);
1402     reg_pairs_saved_count++;
1403   }
1404
1405   if (saved_register_bits & UNWIND_ARM64_FRAME_X27_X28_PAIR) {
1406     int cfa_offset = reg_pairs_saved_count * -2 * wordsize;
1407     cfa_offset -= wordsize;
1408     row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x27, cfa_offset,
1409                                               true);
1410     cfa_offset -= wordsize;
1411     row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x28, cfa_offset,
1412                                               true);
1413     reg_pairs_saved_count++;
1414   }
1415
1416   // If we use the v8-v15 regnums here, the unwinder will try to grab 128 bits
1417   // off the stack;
1418   // not sure if we have a good way to represent the 64-bitness of these saves.
1419
1420   if (saved_register_bits & UNWIND_ARM64_FRAME_D8_D9_PAIR) {
1421     reg_pairs_saved_count++;
1422   }
1423   if (saved_register_bits & UNWIND_ARM64_FRAME_D10_D11_PAIR) {
1424     reg_pairs_saved_count++;
1425   }
1426   if (saved_register_bits & UNWIND_ARM64_FRAME_D12_D13_PAIR) {
1427     reg_pairs_saved_count++;
1428   }
1429   if (saved_register_bits & UNWIND_ARM64_FRAME_D14_D15_PAIR) {
1430     reg_pairs_saved_count++;
1431   }
1432
1433   unwind_plan.AppendRow(row);
1434   return true;
1435 }
1436
1437 bool CompactUnwindInfo::CreateUnwindPlan_armv7(Target &target,
1438                                                FunctionInfo &function_info,
1439                                                UnwindPlan &unwind_plan,
1440                                                Address pc_or_function_start) {
1441   unwind_plan.SetSourceName("compact unwind info");
1442   unwind_plan.SetSourcedFromCompiler(eLazyBoolYes);
1443   unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
1444   unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo);
1445   unwind_plan.SetRegisterKind(eRegisterKindEHFrame);
1446
1447   unwind_plan.SetLSDAAddress(function_info.lsda_address);
1448   unwind_plan.SetPersonalityFunctionPtr(function_info.personality_ptr_address);
1449
1450   UnwindPlan::RowSP row(new UnwindPlan::Row);
1451
1452   const int wordsize = 4;
1453   int mode = function_info.encoding & UNWIND_ARM_MODE_MASK;
1454
1455   if (mode == UNWIND_ARM_MODE_DWARF)
1456     return false;
1457
1458   uint32_t stack_adjust = (EXTRACT_BITS(function_info.encoding,
1459                                         UNWIND_ARM_FRAME_STACK_ADJUST_MASK)) *
1460                           wordsize;
1461
1462   row->GetCFAValue().SetIsRegisterPlusOffset(arm_r7,
1463                                              (2 * wordsize) + stack_adjust);
1464   row->SetOffset(0);
1465   row->SetRegisterLocationToAtCFAPlusOffset(
1466       arm_r7, (wordsize * -2) - stack_adjust, true);
1467   row->SetRegisterLocationToAtCFAPlusOffset(
1468       arm_pc, (wordsize * -1) - stack_adjust, true);
1469   row->SetRegisterLocationToIsCFAPlusOffset(arm_sp, 0, true);
1470
1471   int cfa_offset = -stack_adjust - (2 * wordsize);
1472
1473   uint32_t saved_register_bits = function_info.encoding & 0xff;
1474
1475   if (saved_register_bits & UNWIND_ARM_FRAME_FIRST_PUSH_R6) {
1476     cfa_offset -= wordsize;
1477     row->SetRegisterLocationToAtCFAPlusOffset(arm_r6, cfa_offset, true);
1478   }
1479
1480   if (saved_register_bits & UNWIND_ARM_FRAME_FIRST_PUSH_R5) {
1481     cfa_offset -= wordsize;
1482     row->SetRegisterLocationToAtCFAPlusOffset(arm_r5, cfa_offset, true);
1483   }
1484
1485   if (saved_register_bits & UNWIND_ARM_FRAME_FIRST_PUSH_R4) {
1486     cfa_offset -= wordsize;
1487     row->SetRegisterLocationToAtCFAPlusOffset(arm_r4, cfa_offset, true);
1488   }
1489
1490   if (saved_register_bits & UNWIND_ARM_FRAME_SECOND_PUSH_R12) {
1491     cfa_offset -= wordsize;
1492     row->SetRegisterLocationToAtCFAPlusOffset(arm_r12, cfa_offset, true);
1493   }
1494
1495   if (saved_register_bits & UNWIND_ARM_FRAME_SECOND_PUSH_R11) {
1496     cfa_offset -= wordsize;
1497     row->SetRegisterLocationToAtCFAPlusOffset(arm_r11, cfa_offset, true);
1498   }
1499
1500   if (saved_register_bits & UNWIND_ARM_FRAME_SECOND_PUSH_R10) {
1501     cfa_offset -= wordsize;
1502     row->SetRegisterLocationToAtCFAPlusOffset(arm_r10, cfa_offset, true);
1503   }
1504
1505   if (saved_register_bits & UNWIND_ARM_FRAME_SECOND_PUSH_R9) {
1506     cfa_offset -= wordsize;
1507     row->SetRegisterLocationToAtCFAPlusOffset(arm_r9, cfa_offset, true);
1508   }
1509
1510   if (saved_register_bits & UNWIND_ARM_FRAME_SECOND_PUSH_R8) {
1511     cfa_offset -= wordsize;
1512     row->SetRegisterLocationToAtCFAPlusOffset(arm_r8, cfa_offset, true);
1513   }
1514
1515   if (mode == UNWIND_ARM_MODE_FRAME_D) {
1516     uint32_t d_reg_bits =
1517         EXTRACT_BITS(function_info.encoding, UNWIND_ARM_FRAME_D_REG_COUNT_MASK);
1518     switch (d_reg_bits) {
1519     case 0:
1520       // vpush {d8}
1521       cfa_offset -= 8;
1522       row->SetRegisterLocationToAtCFAPlusOffset(arm_d8, cfa_offset, true);
1523       break;
1524     case 1:
1525       // vpush {d10}
1526       // vpush {d8}
1527       cfa_offset -= 8;
1528       row->SetRegisterLocationToAtCFAPlusOffset(arm_d10, cfa_offset, true);
1529       cfa_offset -= 8;
1530       row->SetRegisterLocationToAtCFAPlusOffset(arm_d8, cfa_offset, true);
1531       break;
1532     case 2:
1533       // vpush {d12}
1534       // vpush {d10}
1535       // vpush {d8}
1536       cfa_offset -= 8;
1537       row->SetRegisterLocationToAtCFAPlusOffset(arm_d12, cfa_offset, true);
1538       cfa_offset -= 8;
1539       row->SetRegisterLocationToAtCFAPlusOffset(arm_d10, cfa_offset, true);
1540       cfa_offset -= 8;
1541       row->SetRegisterLocationToAtCFAPlusOffset(arm_d8, cfa_offset, true);
1542       break;
1543     case 3:
1544       // vpush {d14}
1545       // vpush {d12}
1546       // vpush {d10}
1547       // vpush {d8}
1548       cfa_offset -= 8;
1549       row->SetRegisterLocationToAtCFAPlusOffset(arm_d14, cfa_offset, true);
1550       cfa_offset -= 8;
1551       row->SetRegisterLocationToAtCFAPlusOffset(arm_d12, cfa_offset, true);
1552       cfa_offset -= 8;
1553       row->SetRegisterLocationToAtCFAPlusOffset(arm_d10, cfa_offset, true);
1554       cfa_offset -= 8;
1555       row->SetRegisterLocationToAtCFAPlusOffset(arm_d8, cfa_offset, true);
1556       break;
1557     case 4:
1558       // vpush {d14}
1559       // vpush {d12}
1560       // sp = (sp - 24) & (-16);
1561       // vst   {d8, d9, d10}
1562       cfa_offset -= 8;
1563       row->SetRegisterLocationToAtCFAPlusOffset(arm_d14, cfa_offset, true);
1564       cfa_offset -= 8;
1565       row->SetRegisterLocationToAtCFAPlusOffset(arm_d12, cfa_offset, true);
1566
1567       // FIXME we don't have a way to represent reg saves at an specific
1568       // alignment short of
1569       // coming up with some DWARF location description.
1570
1571       break;
1572     case 5:
1573       // vpush {d14}
1574       // sp = (sp - 40) & (-16);
1575       // vst   {d8, d9, d10, d11}
1576       // vst   {d12}
1577
1578       cfa_offset -= 8;
1579       row->SetRegisterLocationToAtCFAPlusOffset(arm_d14, cfa_offset, true);
1580
1581       // FIXME we don't have a way to represent reg saves at an specific
1582       // alignment short of
1583       // coming up with some DWARF location description.
1584
1585       break;
1586     case 6:
1587       // sp = (sp - 56) & (-16);
1588       // vst   {d8, d9, d10, d11}
1589       // vst   {d12, d13, d14}
1590
1591       // FIXME we don't have a way to represent reg saves at an specific
1592       // alignment short of
1593       // coming up with some DWARF location description.
1594
1595       break;
1596     case 7:
1597       // sp = (sp - 64) & (-16);
1598       // vst   {d8, d9, d10, d11}
1599       // vst   {d12, d13, d14, d15}
1600
1601       // FIXME we don't have a way to represent reg saves at an specific
1602       // alignment short of
1603       // coming up with some DWARF location description.
1604
1605       break;
1606     }
1607   }
1608
1609   unwind_plan.AppendRow(row);
1610   return true;
1611 }