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