CompactUnwindInfo.cpp revision 360784
1259701Sdim//===-- CompactUnwindInfo.cpp -----------------------------------*- C++ -*-===//
2259701Sdim//
3259701Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4259701Sdim// See https://llvm.org/LICENSE.txt for license information.
5259701Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6259701Sdim//
7259701Sdim//===----------------------------------------------------------------------===//
8259701Sdim
9259701Sdim#include "lldb/Symbol/CompactUnwindInfo.h"
10259701Sdim#include "lldb/Core/Module.h"
11259701Sdim#include "lldb/Core/Section.h"
12259701Sdim#include "lldb/Symbol/ObjectFile.h"
13259701Sdim#include "lldb/Symbol/UnwindPlan.h"
14259701Sdim#include "lldb/Target/Process.h"
15259701Sdim#include "lldb/Target/Target.h"
16259701Sdim#include "lldb/Utility/ArchSpec.h"
17259701Sdim#include "lldb/Utility/DataBufferHeap.h"
18259701Sdim#include "lldb/Utility/Log.h"
19259701Sdim#include "lldb/Utility/StreamString.h"
20259701Sdim
21259701Sdim#include "llvm/Support/MathExtras.h"
22259701Sdim
23259701Sdim#include <algorithm>
24259701Sdim#include <memory>
25259701Sdim
26259701Sdimusing namespace lldb;
27259701Sdimusing namespace lldb_private;
28259701Sdim
29259701Sdimnamespace lldb_private {
30259701Sdim
31259701Sdim// Constants from <mach-o/compact_unwind_encoding.h>
32259701Sdim
33259701SdimFLAGS_ANONYMOUS_ENUM(){
34259701Sdim    UNWIND_IS_NOT_FUNCTION_START = 0x80000000, UNWIND_HAS_LSDA = 0x40000000,
35259701Sdim    UNWIND_PERSONALITY_MASK = 0x30000000,
36259701Sdim};
37259701Sdim
38259701SdimFLAGS_ANONYMOUS_ENUM(){
39259701Sdim    UNWIND_X86_MODE_MASK = 0x0F000000,
40    UNWIND_X86_MODE_EBP_FRAME = 0x01000000,
41    UNWIND_X86_MODE_STACK_IMMD = 0x02000000,
42    UNWIND_X86_MODE_STACK_IND = 0x03000000,
43    UNWIND_X86_MODE_DWARF = 0x04000000,
44
45    UNWIND_X86_EBP_FRAME_REGISTERS = 0x00007FFF,
46    UNWIND_X86_EBP_FRAME_OFFSET = 0x00FF0000,
47
48    UNWIND_X86_FRAMELESS_STACK_SIZE = 0x00FF0000,
49    UNWIND_X86_FRAMELESS_STACK_ADJUST = 0x0000E000,
50    UNWIND_X86_FRAMELESS_STACK_REG_COUNT = 0x00001C00,
51    UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION = 0x000003FF,
52
53    UNWIND_X86_DWARF_SECTION_OFFSET = 0x00FFFFFF,
54};
55
56enum {
57  UNWIND_X86_REG_NONE = 0,
58  UNWIND_X86_REG_EBX = 1,
59  UNWIND_X86_REG_ECX = 2,
60  UNWIND_X86_REG_EDX = 3,
61  UNWIND_X86_REG_EDI = 4,
62  UNWIND_X86_REG_ESI = 5,
63  UNWIND_X86_REG_EBP = 6,
64};
65
66FLAGS_ANONYMOUS_ENUM(){
67    UNWIND_X86_64_MODE_MASK = 0x0F000000,
68    UNWIND_X86_64_MODE_RBP_FRAME = 0x01000000,
69    UNWIND_X86_64_MODE_STACK_IMMD = 0x02000000,
70    UNWIND_X86_64_MODE_STACK_IND = 0x03000000,
71    UNWIND_X86_64_MODE_DWARF = 0x04000000,
72
73    UNWIND_X86_64_RBP_FRAME_REGISTERS = 0x00007FFF,
74    UNWIND_X86_64_RBP_FRAME_OFFSET = 0x00FF0000,
75
76    UNWIND_X86_64_FRAMELESS_STACK_SIZE = 0x00FF0000,
77    UNWIND_X86_64_FRAMELESS_STACK_ADJUST = 0x0000E000,
78    UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT = 0x00001C00,
79    UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION = 0x000003FF,
80
81    UNWIND_X86_64_DWARF_SECTION_OFFSET = 0x00FFFFFF,
82};
83
84enum {
85  UNWIND_X86_64_REG_NONE = 0,
86  UNWIND_X86_64_REG_RBX = 1,
87  UNWIND_X86_64_REG_R12 = 2,
88  UNWIND_X86_64_REG_R13 = 3,
89  UNWIND_X86_64_REG_R14 = 4,
90  UNWIND_X86_64_REG_R15 = 5,
91  UNWIND_X86_64_REG_RBP = 6,
92};
93
94FLAGS_ANONYMOUS_ENUM(){
95    UNWIND_ARM64_MODE_MASK = 0x0F000000,
96    UNWIND_ARM64_MODE_FRAMELESS = 0x02000000,
97    UNWIND_ARM64_MODE_DWARF = 0x03000000,
98    UNWIND_ARM64_MODE_FRAME = 0x04000000,
99
100    UNWIND_ARM64_FRAME_X19_X20_PAIR = 0x00000001,
101    UNWIND_ARM64_FRAME_X21_X22_PAIR = 0x00000002,
102    UNWIND_ARM64_FRAME_X23_X24_PAIR = 0x00000004,
103    UNWIND_ARM64_FRAME_X25_X26_PAIR = 0x00000008,
104    UNWIND_ARM64_FRAME_X27_X28_PAIR = 0x00000010,
105    UNWIND_ARM64_FRAME_D8_D9_PAIR = 0x00000100,
106    UNWIND_ARM64_FRAME_D10_D11_PAIR = 0x00000200,
107    UNWIND_ARM64_FRAME_D12_D13_PAIR = 0x00000400,
108    UNWIND_ARM64_FRAME_D14_D15_PAIR = 0x00000800,
109
110    UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK = 0x00FFF000,
111    UNWIND_ARM64_DWARF_SECTION_OFFSET = 0x00FFFFFF,
112};
113
114FLAGS_ANONYMOUS_ENUM(){
115    UNWIND_ARM_MODE_MASK = 0x0F000000,
116    UNWIND_ARM_MODE_FRAME = 0x01000000,
117    UNWIND_ARM_MODE_FRAME_D = 0x02000000,
118    UNWIND_ARM_MODE_DWARF = 0x04000000,
119
120    UNWIND_ARM_FRAME_STACK_ADJUST_MASK = 0x00C00000,
121
122    UNWIND_ARM_FRAME_FIRST_PUSH_R4 = 0x00000001,
123    UNWIND_ARM_FRAME_FIRST_PUSH_R5 = 0x00000002,
124    UNWIND_ARM_FRAME_FIRST_PUSH_R6 = 0x00000004,
125
126    UNWIND_ARM_FRAME_SECOND_PUSH_R8 = 0x00000008,
127    UNWIND_ARM_FRAME_SECOND_PUSH_R9 = 0x00000010,
128    UNWIND_ARM_FRAME_SECOND_PUSH_R10 = 0x00000020,
129    UNWIND_ARM_FRAME_SECOND_PUSH_R11 = 0x00000040,
130    UNWIND_ARM_FRAME_SECOND_PUSH_R12 = 0x00000080,
131
132    UNWIND_ARM_FRAME_D_REG_COUNT_MASK = 0x00000700,
133
134    UNWIND_ARM_DWARF_SECTION_OFFSET = 0x00FFFFFF,
135};
136}
137
138#ifndef UNWIND_SECOND_LEVEL_REGULAR
139#define UNWIND_SECOND_LEVEL_REGULAR 2
140#endif
141
142#ifndef UNWIND_SECOND_LEVEL_COMPRESSED
143#define UNWIND_SECOND_LEVEL_COMPRESSED 3
144#endif
145
146#ifndef UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET
147#define UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET(entry) (entry & 0x00FFFFFF)
148#endif
149
150#ifndef UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX
151#define UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX(entry)                     \
152  ((entry >> 24) & 0xFF)
153#endif
154
155#define EXTRACT_BITS(value, mask)                                              \
156  ((value >>                                                                   \
157    llvm::countTrailingZeros(static_cast<uint32_t>(mask), llvm::ZB_Width)) &   \
158   (((1 << llvm::countPopulation(static_cast<uint32_t>(mask)))) - 1))
159
160// constructor
161
162CompactUnwindInfo::CompactUnwindInfo(ObjectFile &objfile, SectionSP &section_sp)
163    : m_objfile(objfile), m_section_sp(section_sp),
164      m_section_contents_if_encrypted(), m_mutex(), m_indexes(),
165      m_indexes_computed(eLazyBoolCalculate), m_unwindinfo_data(),
166      m_unwindinfo_data_computed(false), m_unwind_header() {}
167
168// destructor
169
170CompactUnwindInfo::~CompactUnwindInfo() {}
171
172bool CompactUnwindInfo::GetUnwindPlan(Target &target, Address addr,
173                                      UnwindPlan &unwind_plan) {
174  if (!IsValid(target.GetProcessSP())) {
175    return false;
176  }
177  FunctionInfo function_info;
178  if (GetCompactUnwindInfoForFunction(target, addr, function_info)) {
179    // shortcut return for functions that have no compact unwind
180    if (function_info.encoding == 0)
181      return false;
182
183    if (ArchSpec arch = m_objfile.GetArchitecture()) {
184
185      Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND));
186      if (log && log->GetVerbose()) {
187        StreamString strm;
188        addr.Dump(
189            &strm, nullptr,
190            Address::DumpStyle::DumpStyleResolvedDescriptionNoFunctionArguments,
191            Address::DumpStyle::DumpStyleFileAddress,
192            arch.GetAddressByteSize());
193        LLDB_LOGF(log, "Got compact unwind encoding 0x%x for function %s",
194                  function_info.encoding, strm.GetData());
195      }
196
197      if (function_info.valid_range_offset_start != 0 &&
198          function_info.valid_range_offset_end != 0) {
199        SectionList *sl = m_objfile.GetSectionList();
200        if (sl) {
201          addr_t func_range_start_file_addr =
202              function_info.valid_range_offset_start +
203              m_objfile.GetBaseAddress().GetFileAddress();
204          AddressRange func_range(func_range_start_file_addr,
205                                  function_info.valid_range_offset_end -
206                                      function_info.valid_range_offset_start,
207                                  sl);
208          unwind_plan.SetPlanValidAddressRange(func_range);
209        }
210      }
211
212      if (arch.GetTriple().getArch() == llvm::Triple::x86_64) {
213        return CreateUnwindPlan_x86_64(target, function_info, unwind_plan,
214                                       addr);
215      }
216      if (arch.GetTriple().getArch() == llvm::Triple::aarch64 ||
217          arch.GetTriple().getArch() == llvm::Triple::aarch64_32) {
218        return CreateUnwindPlan_arm64(target, function_info, unwind_plan, addr);
219      }
220      if (arch.GetTriple().getArch() == llvm::Triple::x86) {
221        return CreateUnwindPlan_i386(target, function_info, unwind_plan, addr);
222      }
223      if (arch.GetTriple().getArch() == llvm::Triple::arm ||
224          arch.GetTriple().getArch() == llvm::Triple::thumb) {
225        return CreateUnwindPlan_armv7(target, function_info, unwind_plan, addr);
226      }
227    }
228  }
229  return false;
230}
231
232bool CompactUnwindInfo::IsValid(const ProcessSP &process_sp) {
233  if (m_section_sp.get() == nullptr)
234    return false;
235
236  if (m_indexes_computed == eLazyBoolYes && m_unwindinfo_data_computed)
237    return true;
238
239  ScanIndex(process_sp);
240
241  return m_indexes_computed == eLazyBoolYes && m_unwindinfo_data_computed;
242}
243
244void CompactUnwindInfo::ScanIndex(const ProcessSP &process_sp) {
245  std::lock_guard<std::mutex> guard(m_mutex);
246  if (m_indexes_computed == eLazyBoolYes && m_unwindinfo_data_computed)
247    return;
248
249  // We can't read the index for some reason.
250  if (m_indexes_computed == eLazyBoolNo) {
251    return;
252  }
253
254  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND));
255  if (log)
256    m_objfile.GetModule()->LogMessage(
257        log, "Reading compact unwind first-level indexes");
258
259  if (!m_unwindinfo_data_computed) {
260    if (m_section_sp->IsEncrypted()) {
261      // Can't get section contents of a protected/encrypted section until we
262      // have a live process and can read them out of memory.
263      if (process_sp.get() == nullptr)
264        return;
265      m_section_contents_if_encrypted =
266          std::make_shared<DataBufferHeap>(m_section_sp->GetByteSize(), 0);
267      Status error;
268      if (process_sp->ReadMemory(
269              m_section_sp->GetLoadBaseAddress(&process_sp->GetTarget()),
270              m_section_contents_if_encrypted->GetBytes(),
271              m_section_sp->GetByteSize(),
272              error) == m_section_sp->GetByteSize() &&
273          error.Success()) {
274        m_unwindinfo_data.SetAddressByteSize(
275            process_sp->GetTarget().GetArchitecture().GetAddressByteSize());
276        m_unwindinfo_data.SetByteOrder(
277            process_sp->GetTarget().GetArchitecture().GetByteOrder());
278        m_unwindinfo_data.SetData(m_section_contents_if_encrypted, 0);
279      }
280    } else {
281      m_objfile.ReadSectionData(m_section_sp.get(), m_unwindinfo_data);
282    }
283    if (m_unwindinfo_data.GetByteSize() != m_section_sp->GetByteSize())
284      return;
285    m_unwindinfo_data_computed = true;
286  }
287
288  if (m_unwindinfo_data.GetByteSize() > 0) {
289    offset_t offset = 0;
290
291    // struct unwind_info_section_header
292    // {
293    // uint32_t    version;            // UNWIND_SECTION_VERSION
294    // uint32_t    commonEncodingsArraySectionOffset;
295    // uint32_t    commonEncodingsArrayCount;
296    // uint32_t    personalityArraySectionOffset;
297    // uint32_t    personalityArrayCount;
298    // uint32_t    indexSectionOffset;
299    // uint32_t    indexCount;
300
301    m_unwind_header.version = m_unwindinfo_data.GetU32(&offset);
302    m_unwind_header.common_encodings_array_offset =
303        m_unwindinfo_data.GetU32(&offset);
304    m_unwind_header.common_encodings_array_count =
305        m_unwindinfo_data.GetU32(&offset);
306    m_unwind_header.personality_array_offset =
307        m_unwindinfo_data.GetU32(&offset);
308    m_unwind_header.personality_array_count = m_unwindinfo_data.GetU32(&offset);
309    uint32_t indexSectionOffset = m_unwindinfo_data.GetU32(&offset);
310
311    uint32_t indexCount = m_unwindinfo_data.GetU32(&offset);
312
313    if (m_unwind_header.common_encodings_array_offset >
314            m_unwindinfo_data.GetByteSize() ||
315        m_unwind_header.personality_array_offset >
316            m_unwindinfo_data.GetByteSize() ||
317        indexSectionOffset > m_unwindinfo_data.GetByteSize() ||
318        offset > m_unwindinfo_data.GetByteSize()) {
319      Host::SystemLog(Host::eSystemLogError, "error: Invalid offset "
320                                             "encountered in compact unwind "
321                                             "info, skipping\n");
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
382uint32_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
411lldb::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
451uint32_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
491bool 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 = std::lower_bound(m_indexes.begin(), m_indexes.end(), 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
692enum 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.
715uint32_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
734bool 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  unwind_plan.SetLSDAAddress(function_info.lsda_address);
745  unwind_plan.SetPersonalityFunctionPtr(function_info.personality_ptr_address);
746
747  UnwindPlan::RowSP row(new UnwindPlan::Row);
748
749  const int wordsize = 8;
750  int mode = function_info.encoding & UNWIND_X86_64_MODE_MASK;
751  switch (mode) {
752  case UNWIND_X86_64_MODE_RBP_FRAME: {
753    row->GetCFAValue().SetIsRegisterPlusOffset(
754        translate_to_eh_frame_regnum_x86_64(UNWIND_X86_64_REG_RBP),
755        2 * wordsize);
756    row->SetOffset(0);
757    row->SetRegisterLocationToAtCFAPlusOffset(x86_64_eh_regnum::rbp,
758                                              wordsize * -2, true);
759    row->SetRegisterLocationToAtCFAPlusOffset(x86_64_eh_regnum::rip,
760                                              wordsize * -1, true);
761    row->SetRegisterLocationToIsCFAPlusOffset(x86_64_eh_regnum::rsp, 0, true);
762
763    uint32_t saved_registers_offset =
764        EXTRACT_BITS(function_info.encoding, UNWIND_X86_64_RBP_FRAME_OFFSET);
765
766    uint32_t saved_registers_locations =
767        EXTRACT_BITS(function_info.encoding, UNWIND_X86_64_RBP_FRAME_REGISTERS);
768
769    saved_registers_offset += 2;
770
771    for (int i = 0; i < 5; i++) {
772      uint32_t regnum = saved_registers_locations & 0x7;
773      switch (regnum) {
774      case UNWIND_X86_64_REG_NONE:
775        break;
776      case UNWIND_X86_64_REG_RBX:
777      case UNWIND_X86_64_REG_R12:
778      case UNWIND_X86_64_REG_R13:
779      case UNWIND_X86_64_REG_R14:
780      case UNWIND_X86_64_REG_R15:
781        row->SetRegisterLocationToAtCFAPlusOffset(
782            translate_to_eh_frame_regnum_x86_64(regnum),
783            wordsize * -saved_registers_offset, true);
784        break;
785      }
786      saved_registers_offset--;
787      saved_registers_locations >>= 3;
788    }
789    unwind_plan.AppendRow(row);
790    return true;
791  } break;
792
793  case UNWIND_X86_64_MODE_STACK_IND: {
794    // The clang in Xcode 6 is emitting incorrect compact unwind encodings for
795    // this style of unwind.  It was fixed in llvm r217020. The clang in Xcode
796    // 7 has this fixed.
797    return false;
798  } break;
799
800  case UNWIND_X86_64_MODE_STACK_IMMD: {
801    uint32_t stack_size = EXTRACT_BITS(function_info.encoding,
802                                       UNWIND_X86_64_FRAMELESS_STACK_SIZE);
803    uint32_t register_count = EXTRACT_BITS(
804        function_info.encoding, UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT);
805    uint32_t permutation = EXTRACT_BITS(
806        function_info.encoding, UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION);
807
808    if (mode == UNWIND_X86_64_MODE_STACK_IND &&
809        function_info.valid_range_offset_start != 0) {
810      uint32_t stack_adjust = EXTRACT_BITS(
811          function_info.encoding, UNWIND_X86_64_FRAMELESS_STACK_ADJUST);
812
813      // offset into the function instructions; 0 == beginning of first
814      // instruction
815      uint32_t offset_to_subl_insn = EXTRACT_BITS(
816          function_info.encoding, UNWIND_X86_64_FRAMELESS_STACK_SIZE);
817
818      SectionList *sl = m_objfile.GetSectionList();
819      if (sl) {
820        ProcessSP process_sp = target.GetProcessSP();
821        if (process_sp) {
822          Address subl_payload_addr(function_info.valid_range_offset_start, sl);
823          subl_payload_addr.Slide(offset_to_subl_insn);
824          Status error;
825          uint64_t large_stack_size = process_sp->ReadUnsignedIntegerFromMemory(
826              subl_payload_addr.GetLoadAddress(&target), 4, 0, error);
827          if (large_stack_size != 0 && error.Success()) {
828            // Got the large stack frame size correctly - use it
829            stack_size = large_stack_size + (stack_adjust * wordsize);
830          } else {
831            return false;
832          }
833        } else {
834          return false;
835        }
836      } else {
837        return false;
838      }
839    }
840
841    int32_t offset = mode == UNWIND_X86_64_MODE_STACK_IND
842                         ? stack_size
843                         : stack_size * wordsize;
844    row->GetCFAValue().SetIsRegisterPlusOffset(x86_64_eh_regnum::rsp, offset);
845
846    row->SetOffset(0);
847    row->SetRegisterLocationToAtCFAPlusOffset(x86_64_eh_regnum::rip,
848                                              wordsize * -1, true);
849    row->SetRegisterLocationToIsCFAPlusOffset(x86_64_eh_regnum::rsp, 0, true);
850
851    if (register_count > 0) {
852
853      // We need to include (up to) 6 registers in 10 bits. That would be 18
854      // bits if we just used 3 bits per reg to indicate the order they're
855      // saved on the stack.
856      //
857      // This is done with Lehmer code permutation, e.g. see
858      // http://stackoverflow.com/questions/1506078/fast-permutation-number-
859      // permutation-mapping-algorithms
860      int permunreg[6] = {0, 0, 0, 0, 0, 0};
861
862      // This decodes the variable-base number in the 10 bits and gives us the
863      // Lehmer code sequence which can then be decoded.
864
865      switch (register_count) {
866      case 6:
867        permunreg[0] = permutation / 120; // 120 == 5!
868        permutation -= (permunreg[0] * 120);
869        permunreg[1] = permutation / 24; // 24 == 4!
870        permutation -= (permunreg[1] * 24);
871        permunreg[2] = permutation / 6; // 6 == 3!
872        permutation -= (permunreg[2] * 6);
873        permunreg[3] = permutation / 2; // 2 == 2!
874        permutation -= (permunreg[3] * 2);
875        permunreg[4] = permutation; // 1 == 1!
876        permunreg[5] = 0;
877        break;
878      case 5:
879        permunreg[0] = permutation / 120;
880        permutation -= (permunreg[0] * 120);
881        permunreg[1] = permutation / 24;
882        permutation -= (permunreg[1] * 24);
883        permunreg[2] = permutation / 6;
884        permutation -= (permunreg[2] * 6);
885        permunreg[3] = permutation / 2;
886        permutation -= (permunreg[3] * 2);
887        permunreg[4] = permutation;
888        break;
889      case 4:
890        permunreg[0] = permutation / 60;
891        permutation -= (permunreg[0] * 60);
892        permunreg[1] = permutation / 12;
893        permutation -= (permunreg[1] * 12);
894        permunreg[2] = permutation / 3;
895        permutation -= (permunreg[2] * 3);
896        permunreg[3] = permutation;
897        break;
898      case 3:
899        permunreg[0] = permutation / 20;
900        permutation -= (permunreg[0] * 20);
901        permunreg[1] = permutation / 4;
902        permutation -= (permunreg[1] * 4);
903        permunreg[2] = permutation;
904        break;
905      case 2:
906        permunreg[0] = permutation / 5;
907        permutation -= (permunreg[0] * 5);
908        permunreg[1] = permutation;
909        break;
910      case 1:
911        permunreg[0] = permutation;
912        break;
913      }
914
915      // Decode the Lehmer code for this permutation of the registers v.
916      // http://en.wikipedia.org/wiki/Lehmer_code
917
918      int registers[6] = {UNWIND_X86_64_REG_NONE, UNWIND_X86_64_REG_NONE,
919                          UNWIND_X86_64_REG_NONE, UNWIND_X86_64_REG_NONE,
920                          UNWIND_X86_64_REG_NONE, UNWIND_X86_64_REG_NONE};
921      bool used[7] = {false, false, false, false, false, false, false};
922      for (uint32_t i = 0; i < register_count; i++) {
923        int renum = 0;
924        for (int j = 1; j < 7; j++) {
925          if (!used[j]) {
926            if (renum == permunreg[i]) {
927              registers[i] = j;
928              used[j] = true;
929              break;
930            }
931            renum++;
932          }
933        }
934      }
935
936      uint32_t saved_registers_offset = 1;
937      saved_registers_offset++;
938
939      for (int i = (sizeof(registers) / sizeof(int)) - 1; i >= 0; i--) {
940        switch (registers[i]) {
941        case UNWIND_X86_64_REG_NONE:
942          break;
943        case UNWIND_X86_64_REG_RBX:
944        case UNWIND_X86_64_REG_R12:
945        case UNWIND_X86_64_REG_R13:
946        case UNWIND_X86_64_REG_R14:
947        case UNWIND_X86_64_REG_R15:
948        case UNWIND_X86_64_REG_RBP:
949          row->SetRegisterLocationToAtCFAPlusOffset(
950              translate_to_eh_frame_regnum_x86_64(registers[i]),
951              wordsize * -saved_registers_offset, true);
952          saved_registers_offset++;
953          break;
954        }
955      }
956    }
957    unwind_plan.AppendRow(row);
958    return true;
959  } break;
960
961  case UNWIND_X86_64_MODE_DWARF: {
962    return false;
963  } break;
964
965  case 0: {
966    return false;
967  } break;
968  }
969  return false;
970}
971
972enum i386_eh_regnum {
973  eax = 0,
974  ecx = 1,
975  edx = 2,
976  ebx = 3,
977  ebp = 4,
978  esp = 5,
979  esi = 6,
980  edi = 7,
981  eip = 8 // this is officially the Return Address register number, but close
982          // enough
983};
984
985// Convert the compact_unwind_info.h register numbering scheme to
986// eRegisterKindEHFrame (eh_frame) register numbering scheme.
987uint32_t translate_to_eh_frame_regnum_i386(uint32_t unwind_regno) {
988  switch (unwind_regno) {
989  case UNWIND_X86_REG_EBX:
990    return i386_eh_regnum::ebx;
991  case UNWIND_X86_REG_ECX:
992    return i386_eh_regnum::ecx;
993  case UNWIND_X86_REG_EDX:
994    return i386_eh_regnum::edx;
995  case UNWIND_X86_REG_EDI:
996    return i386_eh_regnum::edi;
997  case UNWIND_X86_REG_ESI:
998    return i386_eh_regnum::esi;
999  case UNWIND_X86_REG_EBP:
1000    return i386_eh_regnum::ebp;
1001  default:
1002    return LLDB_INVALID_REGNUM;
1003  }
1004}
1005
1006bool CompactUnwindInfo::CreateUnwindPlan_i386(Target &target,
1007                                              FunctionInfo &function_info,
1008                                              UnwindPlan &unwind_plan,
1009                                              Address pc_or_function_start) {
1010  unwind_plan.SetSourceName("compact unwind info");
1011  unwind_plan.SetSourcedFromCompiler(eLazyBoolYes);
1012  unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
1013  unwind_plan.SetUnwindPlanForSignalTrap(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
1235enum 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
1267enum 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
1303bool 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.SetUnwindPlanForSignalTrap(eLazyBoolNo);
1311  unwind_plan.SetRegisterKind(eRegisterKindEHFrame);
1312
1313  unwind_plan.SetLSDAAddress(function_info.lsda_address);
1314  unwind_plan.SetPersonalityFunctionPtr(function_info.personality_ptr_address);
1315
1316  UnwindPlan::RowSP row(new UnwindPlan::Row);
1317
1318  const int wordsize = 8;
1319  int mode = function_info.encoding & UNWIND_ARM64_MODE_MASK;
1320
1321  if (mode == UNWIND_ARM64_MODE_DWARF)
1322    return false;
1323
1324  if (mode == UNWIND_ARM64_MODE_FRAMELESS) {
1325    row->SetOffset(0);
1326
1327    uint32_t stack_size =
1328        (EXTRACT_BITS(function_info.encoding,
1329                      UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK)) *
1330        16;
1331
1332    // Our previous Call Frame Address is the stack pointer plus the stack size
1333    row->GetCFAValue().SetIsRegisterPlusOffset(arm64_eh_regnum::sp, stack_size);
1334
1335    // Our previous PC is in the LR
1336    row->SetRegisterLocationToRegister(arm64_eh_regnum::pc, arm64_eh_regnum::ra,
1337                                       true);
1338
1339    unwind_plan.AppendRow(row);
1340    return true;
1341  }
1342
1343  // Should not be possible
1344  if (mode != UNWIND_ARM64_MODE_FRAME)
1345    return false;
1346
1347  // mode == UNWIND_ARM64_MODE_FRAME
1348
1349  row->GetCFAValue().SetIsRegisterPlusOffset(arm64_eh_regnum::fp, 2 * wordsize);
1350  row->SetOffset(0);
1351  row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::fp, wordsize * -2,
1352                                            true);
1353  row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::pc, wordsize * -1,
1354                                            true);
1355  row->SetRegisterLocationToIsCFAPlusOffset(arm64_eh_regnum::sp, 0, true);
1356
1357  int reg_pairs_saved_count = 1;
1358
1359  uint32_t saved_register_bits = function_info.encoding & 0xfff;
1360
1361  if (saved_register_bits & UNWIND_ARM64_FRAME_X19_X20_PAIR) {
1362    int cfa_offset = reg_pairs_saved_count * -2 * wordsize;
1363    cfa_offset -= wordsize;
1364    row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x19, cfa_offset,
1365                                              true);
1366    cfa_offset -= wordsize;
1367    row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x20, cfa_offset,
1368                                              true);
1369    reg_pairs_saved_count++;
1370  }
1371
1372  if (saved_register_bits & UNWIND_ARM64_FRAME_X21_X22_PAIR) {
1373    int cfa_offset = reg_pairs_saved_count * -2 * wordsize;
1374    cfa_offset -= wordsize;
1375    row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x21, cfa_offset,
1376                                              true);
1377    cfa_offset -= wordsize;
1378    row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x22, cfa_offset,
1379                                              true);
1380    reg_pairs_saved_count++;
1381  }
1382
1383  if (saved_register_bits & UNWIND_ARM64_FRAME_X23_X24_PAIR) {
1384    int cfa_offset = reg_pairs_saved_count * -2 * wordsize;
1385    cfa_offset -= wordsize;
1386    row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x23, cfa_offset,
1387                                              true);
1388    cfa_offset -= wordsize;
1389    row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x24, cfa_offset,
1390                                              true);
1391    reg_pairs_saved_count++;
1392  }
1393
1394  if (saved_register_bits & UNWIND_ARM64_FRAME_X25_X26_PAIR) {
1395    int cfa_offset = reg_pairs_saved_count * -2 * wordsize;
1396    cfa_offset -= wordsize;
1397    row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x25, cfa_offset,
1398                                              true);
1399    cfa_offset -= wordsize;
1400    row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x26, cfa_offset,
1401                                              true);
1402    reg_pairs_saved_count++;
1403  }
1404
1405  if (saved_register_bits & UNWIND_ARM64_FRAME_X27_X28_PAIR) {
1406    int cfa_offset = reg_pairs_saved_count * -2 * wordsize;
1407    cfa_offset -= wordsize;
1408    row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x27, cfa_offset,
1409                                              true);
1410    cfa_offset -= wordsize;
1411    row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x28, cfa_offset,
1412                                              true);
1413    reg_pairs_saved_count++;
1414  }
1415
1416  // If we use the v8-v15 regnums here, the unwinder will try to grab 128 bits
1417  // off the stack;
1418  // not sure if we have a good way to represent the 64-bitness of these saves.
1419
1420  if (saved_register_bits & UNWIND_ARM64_FRAME_D8_D9_PAIR) {
1421    reg_pairs_saved_count++;
1422  }
1423  if (saved_register_bits & UNWIND_ARM64_FRAME_D10_D11_PAIR) {
1424    reg_pairs_saved_count++;
1425  }
1426  if (saved_register_bits & UNWIND_ARM64_FRAME_D12_D13_PAIR) {
1427    reg_pairs_saved_count++;
1428  }
1429  if (saved_register_bits & UNWIND_ARM64_FRAME_D14_D15_PAIR) {
1430    reg_pairs_saved_count++;
1431  }
1432
1433  unwind_plan.AppendRow(row);
1434  return true;
1435}
1436
1437bool CompactUnwindInfo::CreateUnwindPlan_armv7(Target &target,
1438                                               FunctionInfo &function_info,
1439                                               UnwindPlan &unwind_plan,
1440                                               Address pc_or_function_start) {
1441  unwind_plan.SetSourceName("compact unwind info");
1442  unwind_plan.SetSourcedFromCompiler(eLazyBoolYes);
1443  unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
1444  unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo);
1445  unwind_plan.SetRegisterKind(eRegisterKindEHFrame);
1446
1447  unwind_plan.SetLSDAAddress(function_info.lsda_address);
1448  unwind_plan.SetPersonalityFunctionPtr(function_info.personality_ptr_address);
1449
1450  UnwindPlan::RowSP row(new UnwindPlan::Row);
1451
1452  const int wordsize = 4;
1453  int mode = function_info.encoding & UNWIND_ARM_MODE_MASK;
1454
1455  if (mode == UNWIND_ARM_MODE_DWARF)
1456    return false;
1457
1458  uint32_t stack_adjust = (EXTRACT_BITS(function_info.encoding,
1459                                        UNWIND_ARM_FRAME_STACK_ADJUST_MASK)) *
1460                          wordsize;
1461
1462  row->GetCFAValue().SetIsRegisterPlusOffset(arm_r7,
1463                                             (2 * wordsize) + stack_adjust);
1464  row->SetOffset(0);
1465  row->SetRegisterLocationToAtCFAPlusOffset(
1466      arm_r7, (wordsize * -2) - stack_adjust, true);
1467  row->SetRegisterLocationToAtCFAPlusOffset(
1468      arm_pc, (wordsize * -1) - stack_adjust, true);
1469  row->SetRegisterLocationToIsCFAPlusOffset(arm_sp, 0, true);
1470
1471  int cfa_offset = -stack_adjust - (2 * wordsize);
1472
1473  uint32_t saved_register_bits = function_info.encoding & 0xff;
1474
1475  if (saved_register_bits & UNWIND_ARM_FRAME_FIRST_PUSH_R6) {
1476    cfa_offset -= wordsize;
1477    row->SetRegisterLocationToAtCFAPlusOffset(arm_r6, cfa_offset, true);
1478  }
1479
1480  if (saved_register_bits & UNWIND_ARM_FRAME_FIRST_PUSH_R5) {
1481    cfa_offset -= wordsize;
1482    row->SetRegisterLocationToAtCFAPlusOffset(arm_r5, cfa_offset, true);
1483  }
1484
1485  if (saved_register_bits & UNWIND_ARM_FRAME_FIRST_PUSH_R4) {
1486    cfa_offset -= wordsize;
1487    row->SetRegisterLocationToAtCFAPlusOffset(arm_r4, cfa_offset, true);
1488  }
1489
1490  if (saved_register_bits & UNWIND_ARM_FRAME_SECOND_PUSH_R12) {
1491    cfa_offset -= wordsize;
1492    row->SetRegisterLocationToAtCFAPlusOffset(arm_r12, cfa_offset, true);
1493  }
1494
1495  if (saved_register_bits & UNWIND_ARM_FRAME_SECOND_PUSH_R11) {
1496    cfa_offset -= wordsize;
1497    row->SetRegisterLocationToAtCFAPlusOffset(arm_r11, cfa_offset, true);
1498  }
1499
1500  if (saved_register_bits & UNWIND_ARM_FRAME_SECOND_PUSH_R10) {
1501    cfa_offset -= wordsize;
1502    row->SetRegisterLocationToAtCFAPlusOffset(arm_r10, cfa_offset, true);
1503  }
1504
1505  if (saved_register_bits & UNWIND_ARM_FRAME_SECOND_PUSH_R9) {
1506    cfa_offset -= wordsize;
1507    row->SetRegisterLocationToAtCFAPlusOffset(arm_r9, cfa_offset, true);
1508  }
1509
1510  if (saved_register_bits & UNWIND_ARM_FRAME_SECOND_PUSH_R8) {
1511    cfa_offset -= wordsize;
1512    row->SetRegisterLocationToAtCFAPlusOffset(arm_r8, cfa_offset, true);
1513  }
1514
1515  if (mode == UNWIND_ARM_MODE_FRAME_D) {
1516    uint32_t d_reg_bits =
1517        EXTRACT_BITS(function_info.encoding, UNWIND_ARM_FRAME_D_REG_COUNT_MASK);
1518    switch (d_reg_bits) {
1519    case 0:
1520      // vpush {d8}
1521      cfa_offset -= 8;
1522      row->SetRegisterLocationToAtCFAPlusOffset(arm_d8, cfa_offset, true);
1523      break;
1524    case 1:
1525      // vpush {d10}
1526      // vpush {d8}
1527      cfa_offset -= 8;
1528      row->SetRegisterLocationToAtCFAPlusOffset(arm_d10, cfa_offset, true);
1529      cfa_offset -= 8;
1530      row->SetRegisterLocationToAtCFAPlusOffset(arm_d8, cfa_offset, true);
1531      break;
1532    case 2:
1533      // vpush {d12}
1534      // vpush {d10}
1535      // vpush {d8}
1536      cfa_offset -= 8;
1537      row->SetRegisterLocationToAtCFAPlusOffset(arm_d12, cfa_offset, true);
1538      cfa_offset -= 8;
1539      row->SetRegisterLocationToAtCFAPlusOffset(arm_d10, cfa_offset, true);
1540      cfa_offset -= 8;
1541      row->SetRegisterLocationToAtCFAPlusOffset(arm_d8, cfa_offset, true);
1542      break;
1543    case 3:
1544      // vpush {d14}
1545      // vpush {d12}
1546      // vpush {d10}
1547      // vpush {d8}
1548      cfa_offset -= 8;
1549      row->SetRegisterLocationToAtCFAPlusOffset(arm_d14, cfa_offset, true);
1550      cfa_offset -= 8;
1551      row->SetRegisterLocationToAtCFAPlusOffset(arm_d12, cfa_offset, true);
1552      cfa_offset -= 8;
1553      row->SetRegisterLocationToAtCFAPlusOffset(arm_d10, cfa_offset, true);
1554      cfa_offset -= 8;
1555      row->SetRegisterLocationToAtCFAPlusOffset(arm_d8, cfa_offset, true);
1556      break;
1557    case 4:
1558      // vpush {d14}
1559      // vpush {d12}
1560      // sp = (sp - 24) & (-16);
1561      // vst   {d8, d9, d10}
1562      cfa_offset -= 8;
1563      row->SetRegisterLocationToAtCFAPlusOffset(arm_d14, cfa_offset, true);
1564      cfa_offset -= 8;
1565      row->SetRegisterLocationToAtCFAPlusOffset(arm_d12, cfa_offset, true);
1566
1567      // FIXME we don't have a way to represent reg saves at an specific
1568      // alignment short of
1569      // coming up with some DWARF location description.
1570
1571      break;
1572    case 5:
1573      // vpush {d14}
1574      // sp = (sp - 40) & (-16);
1575      // vst   {d8, d9, d10, d11}
1576      // vst   {d12}
1577
1578      cfa_offset -= 8;
1579      row->SetRegisterLocationToAtCFAPlusOffset(arm_d14, cfa_offset, true);
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    case 6:
1587      // sp = (sp - 56) & (-16);
1588      // vst   {d8, d9, d10, d11}
1589      // vst   {d12, d13, d14}
1590
1591      // FIXME we don't have a way to represent reg saves at an specific
1592      // alignment short of
1593      // coming up with some DWARF location description.
1594
1595      break;
1596    case 7:
1597      // sp = (sp - 64) & (-16);
1598      // vst   {d8, d9, d10, d11}
1599      // vst   {d12, d13, d14, d15}
1600
1601      // FIXME we don't have a way to represent reg saves at an specific
1602      // alignment short of
1603      // coming up with some DWARF location description.
1604
1605      break;
1606    }
1607  }
1608
1609  unwind_plan.AppendRow(row);
1610  return true;
1611}
1612