1 //===-- CompactUnwindInfo.cpp -----------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 
11 // C Includes
12 // C++ Includes
13 #include <algorithm>
14 
15 #include "lldb/Core/ArchSpec.h"
16 #include "lldb/Core/DataBufferHeap.h"
17 #include "lldb/Core/Log.h"
18 #include "lldb/Core/Module.h"
19 #include "lldb/Core/Section.h"
20 #include "lldb/Core/Section.h"
21 #include "lldb/Core/StreamString.h"
22 #include "lldb/Symbol/CompactUnwindInfo.h"
23 #include "lldb/Symbol/ObjectFile.h"
24 #include "lldb/Symbol/UnwindPlan.h"
25 #include "lldb/Target/Process.h"
26 #include "lldb/Target/Target.h"
27 
28 #include "llvm/Support/MathExtras.h"
29 
30 using namespace lldb;
31 using namespace lldb_private;
32 
33 
34 namespace lldb_private {
35 
36     // Constants from <mach-o/compact_unwind_encoding.h>
37 
38     FLAGS_ANONYMOUS_ENUM()
39     {
40         UNWIND_IS_NOT_FUNCTION_START           = 0x80000000,
41         UNWIND_HAS_LSDA                        = 0x40000000,
42         UNWIND_PERSONALITY_MASK                = 0x30000000,
43     };
44 
45     FLAGS_ANONYMOUS_ENUM()
46     {
47         UNWIND_X86_MODE_MASK                         = 0x0F000000,
48         UNWIND_X86_MODE_EBP_FRAME                    = 0x01000000,
49         UNWIND_X86_MODE_STACK_IMMD                   = 0x02000000,
50         UNWIND_X86_MODE_STACK_IND                    = 0x03000000,
51         UNWIND_X86_MODE_DWARF                        = 0x04000000,
52 
53         UNWIND_X86_EBP_FRAME_REGISTERS               = 0x00007FFF,
54         UNWIND_X86_EBP_FRAME_OFFSET                  = 0x00FF0000,
55 
56         UNWIND_X86_FRAMELESS_STACK_SIZE              = 0x00FF0000,
57         UNWIND_X86_FRAMELESS_STACK_ADJUST            = 0x0000E000,
58         UNWIND_X86_FRAMELESS_STACK_REG_COUNT         = 0x00001C00,
59         UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION   = 0x000003FF,
60 
61         UNWIND_X86_DWARF_SECTION_OFFSET              = 0x00FFFFFF,
62     };
63 
64     enum
65     {
66         UNWIND_X86_REG_NONE     = 0,
67         UNWIND_X86_REG_EBX      = 1,
68         UNWIND_X86_REG_ECX      = 2,
69         UNWIND_X86_REG_EDX      = 3,
70         UNWIND_X86_REG_EDI      = 4,
71         UNWIND_X86_REG_ESI      = 5,
72         UNWIND_X86_REG_EBP      = 6,
73     };
74 
75     FLAGS_ANONYMOUS_ENUM()
76     {
77         UNWIND_X86_64_MODE_MASK                         = 0x0F000000,
78         UNWIND_X86_64_MODE_RBP_FRAME                    = 0x01000000,
79         UNWIND_X86_64_MODE_STACK_IMMD                   = 0x02000000,
80         UNWIND_X86_64_MODE_STACK_IND                    = 0x03000000,
81         UNWIND_X86_64_MODE_DWARF                        = 0x04000000,
82 
83         UNWIND_X86_64_RBP_FRAME_REGISTERS               = 0x00007FFF,
84         UNWIND_X86_64_RBP_FRAME_OFFSET                  = 0x00FF0000,
85 
86         UNWIND_X86_64_FRAMELESS_STACK_SIZE              = 0x00FF0000,
87         UNWIND_X86_64_FRAMELESS_STACK_ADJUST            = 0x0000E000,
88         UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT         = 0x00001C00,
89         UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION   = 0x000003FF,
90 
91         UNWIND_X86_64_DWARF_SECTION_OFFSET              = 0x00FFFFFF,
92     };
93 
94     enum
95     {
96         UNWIND_X86_64_REG_NONE       = 0,
97         UNWIND_X86_64_REG_RBX        = 1,
98         UNWIND_X86_64_REG_R12        = 2,
99         UNWIND_X86_64_REG_R13        = 3,
100         UNWIND_X86_64_REG_R14        = 4,
101         UNWIND_X86_64_REG_R15        = 5,
102         UNWIND_X86_64_REG_RBP        = 6,
103     };
104 }
105 
106 
107 #ifndef UNWIND_SECOND_LEVEL_REGULAR
108 #define UNWIND_SECOND_LEVEL_REGULAR 2
109 #endif
110 
111 #ifndef UNWIND_SECOND_LEVEL_COMPRESSED
112 #define UNWIND_SECOND_LEVEL_COMPRESSED 3
113 #endif
114 
115 #ifndef UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET
116 #define UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET(entry)            (entry & 0x00FFFFFF)
117 #endif
118 
119 #ifndef UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX
120 #define UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX(entry)        ((entry >> 24) & 0xFF)
121 #endif
122 
123 #define EXTRACT_BITS(value, mask) \
124         ( (value >> llvm::countTrailingZeros(static_cast<uint32_t>(mask), llvm::ZB_Width)) & \
125           (((1 << llvm::countPopulation(static_cast<uint32_t>(mask))))-1) )
126 
127 
128 
129 //----------------------
130 // constructor
131 //----------------------
132 
133 CompactUnwindInfo::CompactUnwindInfo(ObjectFile &objfile, SectionSP &section_sp)
134     : m_objfile(objfile),
135       m_section_sp(section_sp),
136       m_section_contents_if_encrypted(),
137       m_mutex(),
138       m_indexes(),
139       m_indexes_computed(eLazyBoolCalculate),
140       m_unwindinfo_data(),
141       m_unwindinfo_data_computed(false),
142       m_unwind_header()
143 {
144 }
145 
146 //----------------------
147 // destructor
148 //----------------------
149 
150 CompactUnwindInfo::~CompactUnwindInfo()
151 {
152 }
153 
154 bool
155 CompactUnwindInfo::GetUnwindPlan (Target &target, Address addr, UnwindPlan& unwind_plan)
156 {
157     if (!IsValid (target.GetProcessSP()))
158     {
159         return false;
160     }
161     FunctionInfo function_info;
162     if (GetCompactUnwindInfoForFunction (target, addr, function_info))
163     {
164         // shortcut return for functions that have no compact unwind
165         if (function_info.encoding == 0)
166             return false;
167 
168         ArchSpec arch;
169         if (m_objfile.GetArchitecture (arch))
170         {
171 
172             Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
173             if (log && log->GetVerbose())
174             {
175                 StreamString strm;
176                 addr.Dump (&strm, NULL, Address::DumpStyle::DumpStyleResolvedDescriptionNoFunctionArguments, Address::DumpStyle::DumpStyleFileAddress, arch.GetAddressByteSize());
177                 log->Printf ("Got compact unwind encoding 0x%x for function %s", function_info.encoding, strm.GetData());
178             }
179 
180             if (function_info.valid_range_offset_start != 0 && function_info.valid_range_offset_end != 0)
181             {
182                 SectionList *sl = m_objfile.GetSectionList ();
183                 if (sl)
184                 {
185                     addr_t func_range_start_file_addr =
186                               function_info.valid_range_offset_start + m_objfile.GetHeaderAddress().GetFileAddress();
187                     AddressRange func_range (func_range_start_file_addr,
188                                       function_info.valid_range_offset_end - function_info.valid_range_offset_start,
189                                       sl);
190                     unwind_plan.SetPlanValidAddressRange (func_range);
191                 }
192             }
193 
194             if (arch.GetTriple().getArch() == llvm::Triple::x86_64)
195             {
196                 return CreateUnwindPlan_x86_64 (target, function_info, unwind_plan, addr);
197             }
198             if (arch.GetTriple().getArch() == llvm::Triple::x86)
199             {
200                 return CreateUnwindPlan_i386 (target, function_info, unwind_plan, addr);
201             }
202         }
203     }
204     return false;
205 }
206 
207 bool
208 CompactUnwindInfo::IsValid (const ProcessSP &process_sp)
209 {
210     if (m_section_sp.get() == nullptr)
211         return false;
212 
213     if (m_indexes_computed == eLazyBoolYes && m_unwindinfo_data_computed)
214         return true;
215 
216     ScanIndex (process_sp);
217 
218     return m_indexes_computed == eLazyBoolYes && m_unwindinfo_data_computed;
219 }
220 
221 void
222 CompactUnwindInfo::ScanIndex (const ProcessSP &process_sp)
223 {
224     std::lock_guard<std::mutex> guard(m_mutex);
225     if (m_indexes_computed == eLazyBoolYes && m_unwindinfo_data_computed)
226         return;
227 
228     // We can't read the index for some reason.
229     if (m_indexes_computed == eLazyBoolNo)
230     {
231         return;
232     }
233 
234     Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
235     if (log)
236         m_objfile.GetModule()->LogMessage(log, "Reading compact unwind first-level indexes");
237 
238     if (m_unwindinfo_data_computed == false)
239     {
240         if (m_section_sp->IsEncrypted())
241         {
242             // Can't get section contents of a protected/encrypted section until we have a live
243             // process and can read them out of memory.
244             if (process_sp.get() == nullptr)
245                 return;
246             m_section_contents_if_encrypted.reset (new DataBufferHeap (m_section_sp->GetByteSize(), 0));
247             Error error;
248             if (process_sp->ReadMemory (
249                         m_section_sp->GetLoadBaseAddress (&process_sp->GetTarget()),
250                         m_section_contents_if_encrypted->GetBytes(),
251                         m_section_sp->GetByteSize(), error) == m_section_sp->GetByteSize() && error.Success())
252             {
253                 m_unwindinfo_data.SetAddressByteSize (process_sp->GetTarget().GetArchitecture().GetAddressByteSize());
254                 m_unwindinfo_data.SetByteOrder (process_sp->GetTarget().GetArchitecture().GetByteOrder());
255                 m_unwindinfo_data.SetData (m_section_contents_if_encrypted, 0);
256             }
257         }
258         else
259         {
260             m_objfile.ReadSectionData (m_section_sp.get(), m_unwindinfo_data);
261         }
262         if (m_unwindinfo_data.GetByteSize() != m_section_sp->GetByteSize())
263             return;
264         m_unwindinfo_data_computed = true;
265     }
266 
267     if (m_unwindinfo_data.GetByteSize() > 0)
268     {
269         offset_t offset = 0;
270 
271                 // struct unwind_info_section_header
272                 // {
273                 // uint32_t    version;            // UNWIND_SECTION_VERSION
274                 // uint32_t    commonEncodingsArraySectionOffset;
275                 // uint32_t    commonEncodingsArrayCount;
276                 // uint32_t    personalityArraySectionOffset;
277                 // uint32_t    personalityArrayCount;
278                 // uint32_t    indexSectionOffset;
279                 // uint32_t    indexCount;
280 
281         m_unwind_header.version = m_unwindinfo_data.GetU32(&offset);
282         m_unwind_header.common_encodings_array_offset = m_unwindinfo_data.GetU32(&offset);
283         m_unwind_header.common_encodings_array_count = m_unwindinfo_data.GetU32(&offset);
284         m_unwind_header.personality_array_offset = m_unwindinfo_data.GetU32(&offset);
285         m_unwind_header.personality_array_count = m_unwindinfo_data.GetU32(&offset);
286         uint32_t indexSectionOffset = m_unwindinfo_data.GetU32(&offset);
287 
288         uint32_t indexCount = m_unwindinfo_data.GetU32(&offset);
289 
290         if (m_unwind_header.common_encodings_array_offset > m_unwindinfo_data.GetByteSize()
291             || m_unwind_header.personality_array_offset > m_unwindinfo_data.GetByteSize()
292             || indexSectionOffset > m_unwindinfo_data.GetByteSize()
293             || offset > m_unwindinfo_data.GetByteSize())
294         {
295             Host::SystemLog (Host::eSystemLogError,
296                     "error: Invalid offset encountered in compact unwind info, skipping\n");
297             // don't trust anything from this compact_unwind section if it looks
298             // blatantly invalid data in the header.
299             m_indexes_computed = eLazyBoolNo;
300             return;
301         }
302 
303         // Parse the basic information from the indexes
304         // We wait to scan the second level page info until it's needed
305 
306             // struct unwind_info_section_header_index_entry
307             // {
308             //     uint32_t        functionOffset;
309             //     uint32_t        secondLevelPagesSectionOffset;
310             //     uint32_t        lsdaIndexArraySectionOffset;
311             // };
312 
313         offset = indexSectionOffset;
314         for (uint32_t idx = 0; idx < indexCount; idx++)
315         {
316             uint32_t function_offset = m_unwindinfo_data.GetU32(&offset);      // functionOffset
317             uint32_t second_level_offset = m_unwindinfo_data.GetU32(&offset);  // secondLevelPagesSectionOffset
318             uint32_t lsda_offset = m_unwindinfo_data.GetU32(&offset);          // lsdaIndexArraySectionOffset
319 
320             if (second_level_offset > m_section_sp->GetByteSize() || lsda_offset > m_section_sp->GetByteSize())
321             {
322                 m_indexes_computed = eLazyBoolNo;
323             }
324 
325             UnwindIndex this_index;
326             this_index.function_offset = function_offset;     //
327             this_index.second_level = second_level_offset;
328             this_index.lsda_array_start = lsda_offset;
329 
330             if (m_indexes.size() > 0)
331             {
332                 m_indexes[m_indexes.size() - 1].lsda_array_end = lsda_offset;
333             }
334 
335             if (second_level_offset == 0)
336             {
337                 this_index.sentinal_entry = true;
338             }
339 
340             m_indexes.push_back (this_index);
341         }
342         m_indexes_computed = eLazyBoolYes;
343     }
344     else
345     {
346         m_indexes_computed = eLazyBoolNo;
347     }
348 }
349 
350 uint32_t
351 CompactUnwindInfo::GetLSDAForFunctionOffset (uint32_t lsda_offset, uint32_t lsda_count, uint32_t function_offset)
352 {
353         // struct unwind_info_section_header_lsda_index_entry
354         // {
355         //         uint32_t        functionOffset;
356         //         uint32_t        lsdaOffset;
357         // };
358 
359     offset_t first_entry = lsda_offset;
360     uint32_t low = 0;
361     uint32_t high = lsda_count;
362     while (low < high)
363     {
364         uint32_t mid = (low + high) / 2;
365         offset_t offset = first_entry + (mid * 8);
366         uint32_t mid_func_offset = m_unwindinfo_data.GetU32(&offset);  // functionOffset
367         uint32_t mid_lsda_offset = m_unwindinfo_data.GetU32(&offset);  // lsdaOffset
368         if (mid_func_offset == function_offset)
369         {
370             return mid_lsda_offset;
371         }
372         if (mid_func_offset < function_offset)
373         {
374             low = mid + 1;
375         }
376         else
377         {
378             high = mid;
379         }
380     }
381     return 0;
382 }
383 
384 lldb::offset_t
385 CompactUnwindInfo::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)
386 {
387     // typedef uint32_t compact_unwind_encoding_t;
388     // struct unwind_info_regular_second_level_entry
389     // {
390     //     uint32_t                    functionOffset;
391     //     compact_unwind_encoding_t    encoding;
392 
393     offset_t first_entry = entry_page_offset;
394 
395     uint32_t low = 0;
396     uint32_t high = entry_count;
397     uint32_t last = high - 1;
398     while (low < high)
399     {
400         uint32_t mid = (low + high) / 2;
401         offset_t offset = first_entry + (mid * 8);
402         uint32_t mid_func_offset = m_unwindinfo_data.GetU32(&offset);   // functionOffset
403         uint32_t next_func_offset = 0;
404         if (mid < last)
405         {
406             offset = first_entry + ((mid + 1) * 8);
407             next_func_offset = m_unwindinfo_data.GetU32(&offset);       // functionOffset
408         }
409         if (mid_func_offset <= function_offset)
410         {
411             if (mid == last || (next_func_offset > function_offset))
412             {
413                 if (entry_func_start_offset)
414                     *entry_func_start_offset = mid_func_offset;
415                 if (mid != last && entry_func_end_offset)
416                     *entry_func_end_offset = next_func_offset;
417                 return first_entry + (mid * 8);
418             }
419             else
420             {
421                 low = mid + 1;
422             }
423         }
424         else
425         {
426             high = mid;
427         }
428     }
429     return LLDB_INVALID_OFFSET;
430 }
431 
432 uint32_t
433 CompactUnwindInfo::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)
434 {
435     offset_t first_entry = entry_page_offset;
436 
437     uint32_t low = 0;
438     uint32_t high = entry_count;
439     uint32_t last = high - 1;
440     while (low < high)
441     {
442         uint32_t mid = (low + high) / 2;
443         offset_t offset = first_entry + (mid * 4);
444         uint32_t entry = m_unwindinfo_data.GetU32(&offset);   // entry
445         uint32_t mid_func_offset = UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET (entry);
446         mid_func_offset += function_offset_base;
447         uint32_t next_func_offset = 0;
448         if (mid < last)
449         {
450             offset = first_entry + ((mid + 1) * 4);
451             uint32_t next_entry = m_unwindinfo_data.GetU32(&offset);       // entry
452             next_func_offset = UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET (next_entry);
453             next_func_offset += function_offset_base;
454         }
455         if (mid_func_offset <= function_offset_to_find)
456         {
457             if (mid == last || (next_func_offset > function_offset_to_find))
458             {
459                 if (entry_func_start_offset)
460                     *entry_func_start_offset = mid_func_offset;
461                 if (mid != last && entry_func_end_offset)
462                     *entry_func_end_offset = next_func_offset;
463                 return UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX (entry);
464             }
465             else
466             {
467                 low = mid + 1;
468             }
469         }
470         else
471         {
472             high = mid;
473         }
474     }
475 
476     return UINT32_MAX;
477 }
478 
479 bool
480 CompactUnwindInfo::GetCompactUnwindInfoForFunction (Target &target, Address address, FunctionInfo &unwind_info)
481 {
482     unwind_info.encoding = 0;
483     unwind_info.lsda_address.Clear();
484     unwind_info.personality_ptr_address.Clear();
485 
486     if (!IsValid (target.GetProcessSP()))
487         return false;
488 
489     addr_t text_section_file_address = LLDB_INVALID_ADDRESS;
490     SectionList *sl = m_objfile.GetSectionList ();
491     if (sl)
492     {
493         SectionSP text_sect = sl->FindSectionByType (eSectionTypeCode, true);
494         if (text_sect.get())
495         {
496            text_section_file_address = text_sect->GetFileAddress();
497         }
498     }
499     if (text_section_file_address == LLDB_INVALID_ADDRESS)
500         return false;
501 
502     addr_t function_offset = address.GetFileAddress() - m_objfile.GetHeaderAddress().GetFileAddress();
503 
504     UnwindIndex key;
505     key.function_offset = function_offset;
506 
507     std::vector<UnwindIndex>::const_iterator it;
508     it = std::lower_bound (m_indexes.begin(), m_indexes.end(), key);
509     if (it == m_indexes.end())
510     {
511         return false;
512     }
513 
514     if (it->function_offset != key.function_offset)
515     {
516         if (it != m_indexes.begin())
517             --it;
518     }
519 
520     if (it->sentinal_entry == true)
521     {
522         return false;
523     }
524 
525     auto next_it = it + 1;
526     if (next_it != m_indexes.end())
527     {
528         // initialize the function offset end range to be the start of the
529         // next index offset.  If we find an entry which is at the end of
530         // the index table, this will establish the range end.
531         unwind_info.valid_range_offset_end = next_it->function_offset;
532     }
533 
534     offset_t second_page_offset = it->second_level;
535     offset_t lsda_array_start = it->lsda_array_start;
536     offset_t lsda_array_count = (it->lsda_array_end - it->lsda_array_start) / 8;
537 
538     offset_t offset = second_page_offset;
539     uint32_t kind = m_unwindinfo_data.GetU32(&offset);  // UNWIND_SECOND_LEVEL_REGULAR or UNWIND_SECOND_LEVEL_COMPRESSED
540 
541     if (kind == UNWIND_SECOND_LEVEL_REGULAR)
542     {
543             // struct unwind_info_regular_second_level_page_header
544             // {
545             //     uint32_t    kind;    // UNWIND_SECOND_LEVEL_REGULAR
546             //     uint16_t    entryPageOffset;
547             //     uint16_t    entryCount;
548 
549             // typedef uint32_t compact_unwind_encoding_t;
550             // struct unwind_info_regular_second_level_entry
551             // {
552             //     uint32_t                    functionOffset;
553             //     compact_unwind_encoding_t    encoding;
554 
555         uint16_t entry_page_offset = m_unwindinfo_data.GetU16(&offset); // entryPageOffset
556         uint16_t entry_count = m_unwindinfo_data.GetU16(&offset);       // entryCount
557 
558         offset_t entry_offset = BinarySearchRegularSecondPage (second_page_offset + entry_page_offset, entry_count, function_offset, &unwind_info.valid_range_offset_start, &unwind_info.valid_range_offset_end);
559         if (entry_offset == LLDB_INVALID_OFFSET)
560         {
561             return false;
562         }
563         entry_offset += 4;                                              // skip over functionOffset
564         unwind_info.encoding = m_unwindinfo_data.GetU32(&entry_offset); // encoding
565         if (unwind_info.encoding & UNWIND_HAS_LSDA)
566         {
567             SectionList *sl = m_objfile.GetSectionList ();
568             if (sl)
569             {
570                 uint32_t lsda_offset = GetLSDAForFunctionOffset (lsda_array_start, lsda_array_count, function_offset);
571                 addr_t objfile_header_file_address = m_objfile.GetHeaderAddress().GetFileAddress();
572                 unwind_info.lsda_address.ResolveAddressUsingFileSections (objfile_header_file_address + lsda_offset, sl);
573             }
574         }
575         if (unwind_info.encoding & UNWIND_PERSONALITY_MASK)
576         {
577             uint32_t personality_index = EXTRACT_BITS (unwind_info.encoding, UNWIND_PERSONALITY_MASK);
578 
579             if (personality_index > 0)
580             {
581                 personality_index--;
582                 if (personality_index < m_unwind_header.personality_array_count)
583                 {
584                     offset_t offset = m_unwind_header.personality_array_offset;
585                     offset += 4 * personality_index;
586                     SectionList *sl = m_objfile.GetSectionList ();
587                     if (sl)
588                     {
589                         uint32_t personality_offset = m_unwindinfo_data.GetU32(&offset);
590                         addr_t objfile_header_file_address = m_objfile.GetHeaderAddress().GetFileAddress();
591                         unwind_info.personality_ptr_address.ResolveAddressUsingFileSections (objfile_header_file_address + personality_offset, sl);
592                     }
593                 }
594             }
595         }
596         return true;
597     }
598     else if (kind == UNWIND_SECOND_LEVEL_COMPRESSED)
599     {
600             // struct unwind_info_compressed_second_level_page_header
601             // {
602             //     uint32_t    kind;    // UNWIND_SECOND_LEVEL_COMPRESSED
603             //     uint16_t    entryPageOffset;         // offset from this 2nd lvl page idx to array of entries
604             //                                          // (an entry has a function offset and index into the encodings)
605             //                                          // NB function offset from the entry in the compressed page
606             //                                          // must be added to the index's functionOffset value.
607             //     uint16_t    entryCount;
608             //     uint16_t    encodingsPageOffset;     // offset from this 2nd lvl page idx to array of encodings
609             //     uint16_t    encodingsCount;
610 
611         uint16_t entry_page_offset = m_unwindinfo_data.GetU16(&offset);     // entryPageOffset
612         uint16_t entry_count = m_unwindinfo_data.GetU16(&offset);           // entryCount
613         uint16_t encodings_page_offset = m_unwindinfo_data.GetU16(&offset); // encodingsPageOffset
614         uint16_t encodings_count = m_unwindinfo_data.GetU16(&offset);       // encodingsCount
615 
616         uint32_t encoding_index = BinarySearchCompressedSecondPage (second_page_offset + entry_page_offset, entry_count, function_offset, it->function_offset, &unwind_info.valid_range_offset_start, &unwind_info.valid_range_offset_end);
617         if (encoding_index == UINT32_MAX || encoding_index >= encodings_count + m_unwind_header.common_encodings_array_count)
618         {
619             return false;
620         }
621         uint32_t encoding = 0;
622         if (encoding_index < m_unwind_header.common_encodings_array_count)
623         {
624             offset = m_unwind_header.common_encodings_array_offset + (encoding_index * sizeof (uint32_t));
625             encoding = m_unwindinfo_data.GetU32(&offset);   // encoding entry from the commonEncodingsArray
626         }
627         else
628         {
629             uint32_t page_specific_entry_index = encoding_index - m_unwind_header.common_encodings_array_count;
630             offset = second_page_offset + encodings_page_offset + (page_specific_entry_index * sizeof (uint32_t));
631             encoding = m_unwindinfo_data.GetU32(&offset);   // encoding entry from the page-specific encoding array
632         }
633         if (encoding == 0)
634             return false;
635 
636         unwind_info.encoding = encoding;
637         if (unwind_info.encoding & UNWIND_HAS_LSDA)
638         {
639             SectionList *sl = m_objfile.GetSectionList ();
640             if (sl)
641             {
642                 uint32_t lsda_offset = GetLSDAForFunctionOffset (lsda_array_start, lsda_array_count, function_offset);
643                 addr_t objfile_header_file_address = m_objfile.GetHeaderAddress().GetFileAddress();
644                 unwind_info.lsda_address.ResolveAddressUsingFileSections (objfile_header_file_address + lsda_offset, sl);
645             }
646         }
647         if (unwind_info.encoding & UNWIND_PERSONALITY_MASK)
648         {
649             uint32_t personality_index = EXTRACT_BITS (unwind_info.encoding, UNWIND_PERSONALITY_MASK);
650 
651             if (personality_index > 0)
652             {
653                 personality_index--;
654                 if (personality_index < m_unwind_header.personality_array_count)
655                 {
656                     offset_t offset = m_unwind_header.personality_array_offset;
657                     offset += 4 * personality_index;
658                     SectionList *sl = m_objfile.GetSectionList ();
659                     if (sl)
660                     {
661                         uint32_t personality_offset = m_unwindinfo_data.GetU32(&offset);
662                         addr_t objfile_header_file_address = m_objfile.GetHeaderAddress().GetFileAddress();
663                         unwind_info.personality_ptr_address.ResolveAddressUsingFileSections (objfile_header_file_address + personality_offset, sl);
664                     }
665                 }
666             }
667         }
668         return true;
669     }
670     return false;
671 }
672 
673 enum x86_64_eh_regnum {
674     rax = 0,
675     rdx = 1,
676     rcx = 2,
677     rbx = 3,
678     rsi = 4,
679     rdi = 5,
680     rbp = 6,
681     rsp = 7,
682     r8 = 8,
683     r9 = 9,
684     r10 = 10,
685     r11 = 11,
686     r12 = 12,
687     r13 = 13,
688     r14 = 14,
689     r15 = 15,
690     rip = 16   // this is officially the Return Address register number, but close enough
691 };
692 
693 // Convert the compact_unwind_info.h register numbering scheme
694 // to eRegisterKindEHFrame (eh_frame) register numbering scheme.
695 uint32_t
696 translate_to_eh_frame_regnum_x86_64 (uint32_t unwind_regno)
697 {
698     switch (unwind_regno)
699     {
700         case UNWIND_X86_64_REG_RBX:
701             return x86_64_eh_regnum::rbx;
702         case UNWIND_X86_64_REG_R12:
703             return x86_64_eh_regnum::r12;
704         case UNWIND_X86_64_REG_R13:
705             return x86_64_eh_regnum::r13;
706         case UNWIND_X86_64_REG_R14:
707             return x86_64_eh_regnum::r14;
708         case UNWIND_X86_64_REG_R15:
709             return x86_64_eh_regnum::r15;
710         case UNWIND_X86_64_REG_RBP:
711             return x86_64_eh_regnum::rbp;
712         default:
713             return LLDB_INVALID_REGNUM;
714     }
715 }
716 
717 bool
718 CompactUnwindInfo::CreateUnwindPlan_x86_64 (Target &target, FunctionInfo &function_info, UnwindPlan &unwind_plan, Address pc_or_function_start)
719 {
720     unwind_plan.SetSourceName ("compact unwind info");
721     unwind_plan.SetSourcedFromCompiler (eLazyBoolYes);
722     unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo);
723     unwind_plan.SetRegisterKind (eRegisterKindEHFrame);
724 
725     unwind_plan.SetLSDAAddress (function_info.lsda_address);
726     unwind_plan.SetPersonalityFunctionPtr (function_info.personality_ptr_address);
727 
728     UnwindPlan::RowSP row (new UnwindPlan::Row);
729 
730     const int wordsize = 8;
731     int mode = function_info.encoding & UNWIND_X86_64_MODE_MASK;
732     switch (mode)
733     {
734         case UNWIND_X86_64_MODE_RBP_FRAME:
735         {
736             row->GetCFAValue().SetIsRegisterPlusOffset (
737                     translate_to_eh_frame_regnum_x86_64 (UNWIND_X86_64_REG_RBP),
738                     2 * wordsize);
739             row->SetOffset (0);
740             row->SetRegisterLocationToAtCFAPlusOffset (x86_64_eh_regnum::rbp, wordsize * -2, true);
741             row->SetRegisterLocationToAtCFAPlusOffset (x86_64_eh_regnum::rip, wordsize * -1, true);
742             row->SetRegisterLocationToIsCFAPlusOffset (x86_64_eh_regnum::rsp, 0, true);
743 
744             uint32_t saved_registers_offset = EXTRACT_BITS (function_info.encoding, UNWIND_X86_64_RBP_FRAME_OFFSET);
745 
746             uint32_t saved_registers_locations = EXTRACT_BITS (function_info.encoding, UNWIND_X86_64_RBP_FRAME_REGISTERS);
747 
748             saved_registers_offset += 2;
749 
750             for (int i = 0; i < 5; i++)
751             {
752                 uint32_t regnum = saved_registers_locations & 0x7;
753                 switch (regnum)
754                 {
755                     case UNWIND_X86_64_REG_NONE:
756                         break;
757                     case UNWIND_X86_64_REG_RBX:
758                     case UNWIND_X86_64_REG_R12:
759                     case UNWIND_X86_64_REG_R13:
760                     case UNWIND_X86_64_REG_R14:
761                     case UNWIND_X86_64_REG_R15:
762                         row->SetRegisterLocationToAtCFAPlusOffset (translate_to_eh_frame_regnum_x86_64 (regnum), wordsize * -saved_registers_offset, true);
763                         break;
764                 }
765                 saved_registers_offset--;
766                 saved_registers_locations >>= 3;
767             }
768             unwind_plan.AppendRow (row);
769             return true;
770         }
771         break;
772 
773         case UNWIND_X86_64_MODE_STACK_IND:
774         {
775             // The clang in Xcode 6 is emitting incorrect compact unwind encodings for this
776             // style of unwind.  It was fixed in llvm r217020.
777             // The clang in Xcode 7 has this fixed.
778             return false;
779         }
780         break;
781 
782         case UNWIND_X86_64_MODE_STACK_IMMD:
783         {
784             uint32_t stack_size = EXTRACT_BITS (function_info.encoding, UNWIND_X86_64_FRAMELESS_STACK_SIZE);
785             uint32_t register_count = EXTRACT_BITS (function_info.encoding, UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT);
786             uint32_t permutation = EXTRACT_BITS (function_info.encoding, UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION);
787 
788             if (mode == UNWIND_X86_64_MODE_STACK_IND && function_info.valid_range_offset_start != 0)
789             {
790                 uint32_t stack_adjust = EXTRACT_BITS (function_info.encoding, UNWIND_X86_64_FRAMELESS_STACK_ADJUST);
791 
792                 // offset into the function instructions; 0 == beginning of first instruction
793                 uint32_t offset_to_subl_insn = EXTRACT_BITS (function_info.encoding, UNWIND_X86_64_FRAMELESS_STACK_SIZE);
794 
795                 SectionList *sl = m_objfile.GetSectionList ();
796                 if (sl)
797                 {
798                     ProcessSP process_sp = target.GetProcessSP();
799                     if (process_sp)
800                     {
801                         Address subl_payload_addr (function_info.valid_range_offset_start, sl);
802                         subl_payload_addr.Slide (offset_to_subl_insn);
803                         Error error;
804                         uint64_t large_stack_size = process_sp->ReadUnsignedIntegerFromMemory (subl_payload_addr.GetLoadAddress (&target),
805                                 4, 0, error);
806                         if (large_stack_size != 0 && error.Success ())
807                         {
808                             // Got the large stack frame size correctly - use it
809                             stack_size = large_stack_size + (stack_adjust * wordsize);
810                         }
811                         else
812                         {
813                             return false;
814                         }
815                     }
816                     else
817                     {
818                         return false;
819                     }
820                 }
821                 else
822                 {
823                     return false;
824                 }
825             }
826 
827             int32_t offset = mode == UNWIND_X86_64_MODE_STACK_IND ? stack_size : stack_size * wordsize;
828             row->GetCFAValue().SetIsRegisterPlusOffset (x86_64_eh_regnum::rsp, offset);
829 
830             row->SetOffset (0);
831             row->SetRegisterLocationToAtCFAPlusOffset (x86_64_eh_regnum::rip, wordsize * -1, true);
832             row->SetRegisterLocationToIsCFAPlusOffset (x86_64_eh_regnum::rsp, 0, true);
833 
834             if (register_count > 0)
835             {
836 
837                 // We need to include (up to) 6 registers in 10 bits.
838                 // That would be 18 bits if we just used 3 bits per reg to indicate
839                 // the order they're saved on the stack.
840                 //
841                 // This is done with Lehmer code permutation, e.g. see
842                 // http://stackoverflow.com/questions/1506078/fast-permutation-number-permutation-mapping-algorithms
843                 int permunreg[6] = {0, 0, 0, 0, 0, 0};
844 
845                 // This decodes the variable-base number in the 10 bits
846                 // and gives us the Lehmer code sequence which can then
847                 // be decoded.
848 
849                 switch (register_count)
850                 {
851                     case 6:
852                         permunreg[0] = permutation/120;    // 120 == 5!
853                         permutation -= (permunreg[0]*120);
854                         permunreg[1] = permutation/24;     // 24 == 4!
855                         permutation -= (permunreg[1]*24);
856                         permunreg[2] = permutation/6;      // 6 == 3!
857                         permutation -= (permunreg[2]*6);
858                         permunreg[3] = permutation/2;      // 2 == 2!
859                         permutation -= (permunreg[3]*2);
860                         permunreg[4] = permutation;        // 1 == 1!
861                         permunreg[5] = 0;
862                         break;
863                     case 5:
864                         permunreg[0] = permutation/120;
865                         permutation -= (permunreg[0]*120);
866                         permunreg[1] = permutation/24;
867                         permutation -= (permunreg[1]*24);
868                         permunreg[2] = permutation/6;
869                         permutation -= (permunreg[2]*6);
870                         permunreg[3] = permutation/2;
871                         permutation -= (permunreg[3]*2);
872                         permunreg[4] = permutation;
873                         break;
874                     case 4:
875                         permunreg[0] = permutation/60;
876                         permutation -= (permunreg[0]*60);
877                         permunreg[1] = permutation/12;
878                         permutation -= (permunreg[1]*12);
879                         permunreg[2] = permutation/3;
880                         permutation -= (permunreg[2]*3);
881                         permunreg[3] = permutation;
882                         break;
883                     case 3:
884                         permunreg[0] = permutation/20;
885                         permutation -= (permunreg[0]*20);
886                         permunreg[1] = permutation/4;
887                         permutation -= (permunreg[1]*4);
888                         permunreg[2] = permutation;
889                         break;
890                     case 2:
891                         permunreg[0] = permutation/5;
892                         permutation -= (permunreg[0]*5);
893                         permunreg[1] = permutation;
894                         break;
895                     case 1:
896                         permunreg[0] = permutation;
897                         break;
898                 }
899 
900                 // Decode the Lehmer code for this permutation of
901                 // the registers v. http://en.wikipedia.org/wiki/Lehmer_code
902 
903                 int registers[6] = { UNWIND_X86_64_REG_NONE, UNWIND_X86_64_REG_NONE, UNWIND_X86_64_REG_NONE, UNWIND_X86_64_REG_NONE, UNWIND_X86_64_REG_NONE, UNWIND_X86_64_REG_NONE };
904                 bool used[7] = { false, false, false, false, false, false, false };
905                 for (uint32_t i = 0; i < register_count; i++)
906                 {
907                     int renum = 0;
908                     for (int j = 1; j < 7; j++)
909                     {
910                         if (used[j] == false)
911                         {
912                             if (renum == permunreg[i])
913                             {
914                                 registers[i] = j;
915                                 used[j] = true;
916                                 break;
917                             }
918                             renum++;
919                         }
920                     }
921                 }
922 
923                 uint32_t saved_registers_offset = 1;
924                 saved_registers_offset++;
925 
926                 for (int i = (sizeof (registers) / sizeof (int)) - 1; i >= 0; i--)
927                 {
928                     switch (registers[i])
929                     {
930                         case UNWIND_X86_64_REG_NONE:
931                             break;
932                         case UNWIND_X86_64_REG_RBX:
933                         case UNWIND_X86_64_REG_R12:
934                         case UNWIND_X86_64_REG_R13:
935                         case UNWIND_X86_64_REG_R14:
936                         case UNWIND_X86_64_REG_R15:
937                         case UNWIND_X86_64_REG_RBP:
938                             row->SetRegisterLocationToAtCFAPlusOffset (translate_to_eh_frame_regnum_x86_64 (registers[i]), wordsize * -saved_registers_offset, true);
939                             saved_registers_offset++;
940                         break;
941                     }
942                 }
943             }
944             unwind_plan.AppendRow (row);
945             return true;
946         }
947         break;
948 
949         case UNWIND_X86_64_MODE_DWARF:
950         {
951             return false;
952         }
953         break;
954 
955         case 0:
956         {
957             return false;
958         }
959         break;
960     }
961     return false;
962 }
963 
964 enum i386_eh_regnum {
965     eax = 0,
966     ecx = 1,
967     edx = 2,
968     ebx = 3,
969     ebp = 4,
970     esp = 5,
971     esi = 6,
972     edi = 7,
973     eip = 8    // this is officially the Return Address register number, but close enough
974 };
975 
976 // Convert the compact_unwind_info.h register numbering scheme
977 // to eRegisterKindEHFrame (eh_frame) register numbering scheme.
978 uint32_t
979 translate_to_eh_frame_regnum_i386 (uint32_t unwind_regno)
980 {
981     switch (unwind_regno)
982     {
983         case UNWIND_X86_REG_EBX:
984             return i386_eh_regnum::ebx;
985         case UNWIND_X86_REG_ECX:
986             return i386_eh_regnum::ecx;
987         case UNWIND_X86_REG_EDX:
988             return i386_eh_regnum::edx;
989         case UNWIND_X86_REG_EDI:
990             return i386_eh_regnum::edi;
991         case UNWIND_X86_REG_ESI:
992             return i386_eh_regnum::esi;
993         case UNWIND_X86_REG_EBP:
994             return i386_eh_regnum::ebp;
995         default:
996             return LLDB_INVALID_REGNUM;
997     }
998 }
999 
1000 
1001 bool
1002 CompactUnwindInfo::CreateUnwindPlan_i386 (Target &target, FunctionInfo &function_info, UnwindPlan &unwind_plan, Address pc_or_function_start)
1003 {
1004     unwind_plan.SetSourceName ("compact unwind info");
1005     unwind_plan.SetSourcedFromCompiler (eLazyBoolYes);
1006     unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo);
1007     unwind_plan.SetRegisterKind (eRegisterKindEHFrame);
1008 
1009     unwind_plan.SetLSDAAddress (function_info.lsda_address);
1010     unwind_plan.SetPersonalityFunctionPtr (function_info.personality_ptr_address);
1011 
1012     UnwindPlan::RowSP row (new UnwindPlan::Row);
1013 
1014     const int wordsize = 4;
1015     int mode = function_info.encoding & UNWIND_X86_MODE_MASK;
1016     switch (mode)
1017     {
1018         case UNWIND_X86_MODE_EBP_FRAME:
1019         {
1020             row->GetCFAValue().SetIsRegisterPlusOffset (
1021                     translate_to_eh_frame_regnum_i386 (UNWIND_X86_REG_EBP), 2 * wordsize);
1022             row->SetOffset (0);
1023             row->SetRegisterLocationToAtCFAPlusOffset (i386_eh_regnum::ebp, wordsize * -2, true);
1024             row->SetRegisterLocationToAtCFAPlusOffset (i386_eh_regnum::eip, wordsize * -1, true);
1025             row->SetRegisterLocationToIsCFAPlusOffset (i386_eh_regnum::esp, 0, true);
1026 
1027             uint32_t saved_registers_offset = EXTRACT_BITS (function_info.encoding, UNWIND_X86_EBP_FRAME_OFFSET);
1028 
1029             uint32_t saved_registers_locations = 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             {
1035                 uint32_t regnum = saved_registers_locations & 0x7;
1036                 switch (regnum)
1037                 {
1038                     case UNWIND_X86_REG_NONE:
1039                         break;
1040                     case UNWIND_X86_REG_EBX:
1041                     case UNWIND_X86_REG_ECX:
1042                     case UNWIND_X86_REG_EDX:
1043                     case UNWIND_X86_REG_EDI:
1044                     case UNWIND_X86_REG_ESI:
1045                         row->SetRegisterLocationToAtCFAPlusOffset (translate_to_eh_frame_regnum_i386 (regnum), wordsize * -saved_registers_offset, true);
1046                         break;
1047                 }
1048                 saved_registers_offset--;
1049                 saved_registers_locations >>= 3;
1050             }
1051             unwind_plan.AppendRow (row);
1052             return true;
1053         }
1054         break;
1055 
1056         case UNWIND_X86_MODE_STACK_IND:
1057         case UNWIND_X86_MODE_STACK_IMMD:
1058         {
1059             uint32_t stack_size = EXTRACT_BITS (function_info.encoding, UNWIND_X86_FRAMELESS_STACK_SIZE);
1060             uint32_t register_count = EXTRACT_BITS (function_info.encoding, UNWIND_X86_FRAMELESS_STACK_REG_COUNT);
1061             uint32_t permutation = EXTRACT_BITS (function_info.encoding, UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION);
1062 
1063             if (mode == UNWIND_X86_MODE_STACK_IND && function_info.valid_range_offset_start != 0)
1064             {
1065                 uint32_t stack_adjust = EXTRACT_BITS (function_info.encoding, UNWIND_X86_FRAMELESS_STACK_ADJUST);
1066 
1067                 // offset into the function instructions; 0 == beginning of first instruction
1068                 uint32_t offset_to_subl_insn = EXTRACT_BITS (function_info.encoding, UNWIND_X86_FRAMELESS_STACK_SIZE);
1069 
1070                 SectionList *sl = m_objfile.GetSectionList ();
1071                 if (sl)
1072                 {
1073                     ProcessSP process_sp = target.GetProcessSP();
1074                     if (process_sp)
1075                     {
1076                         Address subl_payload_addr (function_info.valid_range_offset_start, sl);
1077                         subl_payload_addr.Slide (offset_to_subl_insn);
1078                         Error error;
1079                         uint64_t large_stack_size = process_sp->ReadUnsignedIntegerFromMemory (subl_payload_addr.GetLoadAddress (&target),
1080                                 4, 0, error);
1081                         if (large_stack_size != 0 && error.Success ())
1082                         {
1083                             // Got the large stack frame size correctly - use it
1084                             stack_size = large_stack_size + (stack_adjust * wordsize);
1085                         }
1086                         else
1087                         {
1088                             return false;
1089                         }
1090                     }
1091                     else
1092                     {
1093                         return false;
1094                     }
1095                 }
1096                 else
1097                 {
1098                     return false;
1099                 }
1100             }
1101 
1102             int32_t offset = mode == UNWIND_X86_MODE_STACK_IND ? stack_size : stack_size * wordsize;
1103             row->GetCFAValue().SetIsRegisterPlusOffset (i386_eh_regnum::esp, offset);
1104             row->SetOffset (0);
1105             row->SetRegisterLocationToAtCFAPlusOffset (i386_eh_regnum::eip, wordsize * -1, true);
1106             row->SetRegisterLocationToIsCFAPlusOffset (i386_eh_regnum::esp, 0, true);
1107 
1108             if (register_count > 0)
1109             {
1110 
1111                 // We need to include (up to) 6 registers in 10 bits.
1112                 // That would be 18 bits if we just used 3 bits per reg to indicate
1113                 // the order they're saved on the stack.
1114                 //
1115                 // This is done with Lehmer code permutation, e.g. see
1116                 // http://stackoverflow.com/questions/1506078/fast-permutation-number-permutation-mapping-algorithms
1117                 int permunreg[6] = {0, 0, 0, 0, 0, 0};
1118 
1119                 // This decodes the variable-base number in the 10 bits
1120                 // and gives us the Lehmer code sequence which can then
1121                 // be decoded.
1122 
1123                 switch (register_count)
1124                 {
1125                     case 6:
1126                         permunreg[0] = permutation/120;    // 120 == 5!
1127                         permutation -= (permunreg[0]*120);
1128                         permunreg[1] = permutation/24;     // 24 == 4!
1129                         permutation -= (permunreg[1]*24);
1130                         permunreg[2] = permutation/6;      // 6 == 3!
1131                         permutation -= (permunreg[2]*6);
1132                         permunreg[3] = permutation/2;      // 2 == 2!
1133                         permutation -= (permunreg[3]*2);
1134                         permunreg[4] = permutation;        // 1 == 1!
1135                         permunreg[5] = 0;
1136                         break;
1137                     case 5:
1138                         permunreg[0] = permutation/120;
1139                         permutation -= (permunreg[0]*120);
1140                         permunreg[1] = permutation/24;
1141                         permutation -= (permunreg[1]*24);
1142                         permunreg[2] = permutation/6;
1143                         permutation -= (permunreg[2]*6);
1144                         permunreg[3] = permutation/2;
1145                         permutation -= (permunreg[3]*2);
1146                         permunreg[4] = permutation;
1147                         break;
1148                     case 4:
1149                         permunreg[0] = permutation/60;
1150                         permutation -= (permunreg[0]*60);
1151                         permunreg[1] = permutation/12;
1152                         permutation -= (permunreg[1]*12);
1153                         permunreg[2] = permutation/3;
1154                         permutation -= (permunreg[2]*3);
1155                         permunreg[3] = permutation;
1156                         break;
1157                     case 3:
1158                         permunreg[0] = permutation/20;
1159                         permutation -= (permunreg[0]*20);
1160                         permunreg[1] = permutation/4;
1161                         permutation -= (permunreg[1]*4);
1162                         permunreg[2] = permutation;
1163                         break;
1164                     case 2:
1165                         permunreg[0] = permutation/5;
1166                         permutation -= (permunreg[0]*5);
1167                         permunreg[1] = permutation;
1168                         break;
1169                     case 1:
1170                         permunreg[0] = permutation;
1171                         break;
1172                 }
1173 
1174                 // Decode the Lehmer code for this permutation of
1175                 // the registers v. http://en.wikipedia.org/wiki/Lehmer_code
1176 
1177                 int registers[6] = { UNWIND_X86_REG_NONE, UNWIND_X86_REG_NONE, UNWIND_X86_REG_NONE, UNWIND_X86_REG_NONE, UNWIND_X86_REG_NONE, UNWIND_X86_REG_NONE };
1178                 bool used[7] = { false, false, false, false, false, false, false };
1179                 for (uint32_t i = 0; i < register_count; i++)
1180                 {
1181                     int renum = 0;
1182                     for (int j = 1; j < 7; j++)
1183                     {
1184                         if (used[j] == false)
1185                         {
1186                             if (renum == permunreg[i])
1187                             {
1188                                 registers[i] = j;
1189                                 used[j] = true;
1190                                 break;
1191                             }
1192                             renum++;
1193                         }
1194                     }
1195                 }
1196 
1197                 uint32_t saved_registers_offset = 1;
1198                 saved_registers_offset++;
1199 
1200                 for (int i = (sizeof (registers) / sizeof (int)) - 1; i >= 0; i--)
1201                 {
1202                     switch (registers[i])
1203                     {
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 (translate_to_eh_frame_regnum_i386 (registers[i]), wordsize * -saved_registers_offset, true);
1213                             saved_registers_offset++;
1214                         break;
1215                     }
1216                 }
1217             }
1218 
1219             unwind_plan.AppendRow (row);
1220             return true;
1221         }
1222         break;
1223 
1224         case UNWIND_X86_MODE_DWARF:
1225         {
1226             return false;
1227         }
1228         break;
1229     }
1230     return false;
1231 }
1232