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