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