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