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