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