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