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