blob: 5f23f84277459e1ae7d90e5d34e9925e5a196ac1 [file] [log] [blame]
Jason Molendae589e7e2014-12-08 03:09:00 +00001//===-- 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
Jason Molendae589e7e2014-12-08 03:09:00 +000015#include "lldb/Core/ArchSpec.h"
Zachary Turneraf0f45f2015-03-03 21:05:17 +000016#include "lldb/Core/DataBufferHeap.h"
Jason Molendab12a1362014-12-20 03:12:51 +000017#include "lldb/Core/Log.h"
Jason Molendae589e7e2014-12-08 03:09:00 +000018#include "lldb/Core/Module.h"
19#include "lldb/Core/Section.h"
Jason Molendab12a1362014-12-20 03:12:51 +000020#include "lldb/Core/Section.h"
Jason Molenda5c45c542014-12-21 10:44:54 +000021#include "lldb/Core/StreamString.h"
Jason Molendae589e7e2014-12-08 03:09:00 +000022#include "lldb/Symbol/CompactUnwindInfo.h"
23#include "lldb/Symbol/ObjectFile.h"
24#include "lldb/Symbol/UnwindPlan.h"
Jason Molendab12a1362014-12-20 03:12:51 +000025#include "lldb/Target/Process.h"
26#include "lldb/Target/Target.h"
Jason Molendae589e7e2014-12-08 03:09:00 +000027
Zachary Turner818a3672014-12-08 20:00:33 +000028#include "llvm/Support/MathExtras.h"
29
Jason Molendae589e7e2014-12-08 03:09:00 +000030using namespace lldb;
31using namespace lldb_private;
32
33
34namespace lldb_private {
35
36 // Constants from <mach-o/compact_unwind_encoding.h>
37
Zachary Turner48b475c2015-04-02 20:57:38 +000038 FLAGS_ANONYMOUS_ENUM()
39 {
Jason Molendae589e7e2014-12-08 03:09:00 +000040 UNWIND_IS_NOT_FUNCTION_START = 0x80000000,
41 UNWIND_HAS_LSDA = 0x40000000,
42 UNWIND_PERSONALITY_MASK = 0x30000000,
43 };
44
Zachary Turner48b475c2015-04-02 20:57:38 +000045 FLAGS_ANONYMOUS_ENUM()
46 {
Jason Molendae589e7e2014-12-08 03:09:00 +000047 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
Zachary Turner48b475c2015-04-02 20:57:38 +000064 enum
65 {
Jason Molendae589e7e2014-12-08 03:09:00 +000066 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 };
Zachary Turner48b475c2015-04-02 20:57:38 +000074
75 FLAGS_ANONYMOUS_ENUM()
76 {
Jason Molendae589e7e2014-12-08 03:09:00 +000077 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
Zachary Turner48b475c2015-04-02 20:57:38 +000094 enum
95 {
Jason Molendae589e7e2014-12-08 03:09:00 +000096 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 };
Jason Molendab667c202016-05-25 04:20:28 +0000104
105 FLAGS_ANONYMOUS_ENUM()
106 {
107 UNWIND_ARM64_MODE_MASK = 0x0F000000,
108 UNWIND_ARM64_MODE_FRAMELESS = 0x02000000,
109 UNWIND_ARM64_MODE_DWARF = 0x03000000,
110 UNWIND_ARM64_MODE_FRAME = 0x04000000,
111
112 UNWIND_ARM64_FRAME_X19_X20_PAIR = 0x00000001,
113 UNWIND_ARM64_FRAME_X21_X22_PAIR = 0x00000002,
114 UNWIND_ARM64_FRAME_X23_X24_PAIR = 0x00000004,
115 UNWIND_ARM64_FRAME_X25_X26_PAIR = 0x00000008,
116 UNWIND_ARM64_FRAME_X27_X28_PAIR = 0x00000010,
117 UNWIND_ARM64_FRAME_D8_D9_PAIR = 0x00000100,
118 UNWIND_ARM64_FRAME_D10_D11_PAIR = 0x00000200,
119 UNWIND_ARM64_FRAME_D12_D13_PAIR = 0x00000400,
120 UNWIND_ARM64_FRAME_D14_D15_PAIR = 0x00000800,
121
122 UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK = 0x00FFF000,
123 UNWIND_ARM64_DWARF_SECTION_OFFSET = 0x00FFFFFF,
124 };
Vince Harrond7e6a4f2015-05-13 00:25:54 +0000125}
Jason Molendae589e7e2014-12-08 03:09:00 +0000126
127
128#ifndef UNWIND_SECOND_LEVEL_REGULAR
129#define UNWIND_SECOND_LEVEL_REGULAR 2
130#endif
131
132#ifndef UNWIND_SECOND_LEVEL_COMPRESSED
133#define UNWIND_SECOND_LEVEL_COMPRESSED 3
134#endif
135
136#ifndef UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET
137#define UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET(entry) (entry & 0x00FFFFFF)
138#endif
139
140#ifndef UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX
141#define UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX(entry) ((entry >> 24) & 0xFF)
142#endif
143
144#define EXTRACT_BITS(value, mask) \
Zachary Turner818a3672014-12-08 20:00:33 +0000145 ( (value >> llvm::countTrailingZeros(static_cast<uint32_t>(mask), llvm::ZB_Width)) & \
Benjamin Kramer2ea19612015-02-12 16:16:56 +0000146 (((1 << llvm::countPopulation(static_cast<uint32_t>(mask))))-1) )
Jason Molendae589e7e2014-12-08 03:09:00 +0000147
148
149
150//----------------------
151// constructor
152//----------------------
153
Saleem Abdulrasoolbb19a132016-05-19 05:13:57 +0000154CompactUnwindInfo::CompactUnwindInfo(ObjectFile &objfile, SectionSP &section_sp)
155 : m_objfile(objfile),
156 m_section_sp(section_sp),
157 m_section_contents_if_encrypted(),
158 m_mutex(),
159 m_indexes(),
160 m_indexes_computed(eLazyBoolCalculate),
161 m_unwindinfo_data(),
162 m_unwindinfo_data_computed(false),
163 m_unwind_header()
Jason Molendae589e7e2014-12-08 03:09:00 +0000164{
Jason Molendae589e7e2014-12-08 03:09:00 +0000165}
166
167//----------------------
168// destructor
169//----------------------
170
171CompactUnwindInfo::~CompactUnwindInfo()
172{
173}
174
175bool
176CompactUnwindInfo::GetUnwindPlan (Target &target, Address addr, UnwindPlan& unwind_plan)
177{
Jason Molendab12a1362014-12-20 03:12:51 +0000178 if (!IsValid (target.GetProcessSP()))
Jason Molendae589e7e2014-12-08 03:09:00 +0000179 {
180 return false;
181 }
182 FunctionInfo function_info;
183 if (GetCompactUnwindInfoForFunction (target, addr, function_info))
184 {
185 // shortcut return for functions that have no compact unwind
186 if (function_info.encoding == 0)
187 return false;
188
189 ArchSpec arch;
190 if (m_objfile.GetArchitecture (arch))
191 {
Jason Molenda5c45c542014-12-21 10:44:54 +0000192
193 Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
194 if (log && log->GetVerbose())
195 {
196 StreamString strm;
197 addr.Dump (&strm, NULL, Address::DumpStyle::DumpStyleResolvedDescriptionNoFunctionArguments, Address::DumpStyle::DumpStyleFileAddress, arch.GetAddressByteSize());
198 log->Printf ("Got compact unwind encoding 0x%x for function %s", function_info.encoding, strm.GetData());
199 }
200
201 if (function_info.valid_range_offset_start != 0 && function_info.valid_range_offset_end != 0)
202 {
203 SectionList *sl = m_objfile.GetSectionList ();
204 if (sl)
205 {
206 addr_t func_range_start_file_addr =
207 function_info.valid_range_offset_start + m_objfile.GetHeaderAddress().GetFileAddress();
208 AddressRange func_range (func_range_start_file_addr,
209 function_info.valid_range_offset_end - function_info.valid_range_offset_start,
210 sl);
211 unwind_plan.SetPlanValidAddressRange (func_range);
212 }
213 }
214
Jason Molendae589e7e2014-12-08 03:09:00 +0000215 if (arch.GetTriple().getArch() == llvm::Triple::x86_64)
216 {
217 return CreateUnwindPlan_x86_64 (target, function_info, unwind_plan, addr);
218 }
Jason Molendab667c202016-05-25 04:20:28 +0000219 if (arch.GetTriple().getArch() == llvm::Triple::aarch64)
220 {
221 return CreateUnwindPlan_arm64 (target, function_info, unwind_plan, addr);
222 }
Jason Molendae589e7e2014-12-08 03:09:00 +0000223 if (arch.GetTriple().getArch() == llvm::Triple::x86)
224 {
225 return CreateUnwindPlan_i386 (target, function_info, unwind_plan, addr);
226 }
227 }
228 }
229 return false;
230}
231
232bool
Jason Molendab12a1362014-12-20 03:12:51 +0000233CompactUnwindInfo::IsValid (const ProcessSP &process_sp)
Jason Molendae589e7e2014-12-08 03:09:00 +0000234{
Jason Molendab12a1362014-12-20 03:12:51 +0000235 if (m_section_sp.get() == nullptr)
Jason Molendae589e7e2014-12-08 03:09:00 +0000236 return false;
237
238 if (m_indexes_computed == eLazyBoolYes && m_unwindinfo_data_computed)
239 return true;
240
Jason Molendab12a1362014-12-20 03:12:51 +0000241 ScanIndex (process_sp);
Jason Molendae589e7e2014-12-08 03:09:00 +0000242
243 return m_indexes_computed == eLazyBoolYes && m_unwindinfo_data_computed;
244}
245
246void
Jason Molendab12a1362014-12-20 03:12:51 +0000247CompactUnwindInfo::ScanIndex (const ProcessSP &process_sp)
Jason Molendae589e7e2014-12-08 03:09:00 +0000248{
Saleem Abdulrasoolbb19a132016-05-19 05:13:57 +0000249 std::lock_guard<std::mutex> guard(m_mutex);
Jason Molendae589e7e2014-12-08 03:09:00 +0000250 if (m_indexes_computed == eLazyBoolYes && m_unwindinfo_data_computed)
251 return;
252
253 // We can't read the index for some reason.
254 if (m_indexes_computed == eLazyBoolNo)
255 {
256 return;
257 }
258
Jason Molenda5c45c542014-12-21 10:44:54 +0000259 Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
260 if (log)
261 m_objfile.GetModule()->LogMessage(log, "Reading compact unwind first-level indexes");
262
Jason Molendae589e7e2014-12-08 03:09:00 +0000263 if (m_unwindinfo_data_computed == false)
264 {
Jason Molendab12a1362014-12-20 03:12:51 +0000265 if (m_section_sp->IsEncrypted())
266 {
267 // Can't get section contents of a protected/encrypted section until we have a live
268 // process and can read them out of memory.
269 if (process_sp.get() == nullptr)
270 return;
271 m_section_contents_if_encrypted.reset (new DataBufferHeap (m_section_sp->GetByteSize(), 0));
272 Error error;
273 if (process_sp->ReadMemory (
274 m_section_sp->GetLoadBaseAddress (&process_sp->GetTarget()),
275 m_section_contents_if_encrypted->GetBytes(),
276 m_section_sp->GetByteSize(), error) == m_section_sp->GetByteSize() && error.Success())
277 {
278 m_unwindinfo_data.SetAddressByteSize (process_sp->GetTarget().GetArchitecture().GetAddressByteSize());
279 m_unwindinfo_data.SetByteOrder (process_sp->GetTarget().GetArchitecture().GetByteOrder());
280 m_unwindinfo_data.SetData (m_section_contents_if_encrypted, 0);
281 }
282 }
283 else
284 {
285 m_objfile.ReadSectionData (m_section_sp.get(), m_unwindinfo_data);
286 }
287 if (m_unwindinfo_data.GetByteSize() != m_section_sp->GetByteSize())
288 return;
Jason Molendae589e7e2014-12-08 03:09:00 +0000289 m_unwindinfo_data_computed = true;
290 }
291
292 if (m_unwindinfo_data.GetByteSize() > 0)
293 {
294 offset_t offset = 0;
295
296 // struct unwind_info_section_header
297 // {
298 // uint32_t version; // UNWIND_SECTION_VERSION
299 // uint32_t commonEncodingsArraySectionOffset;
300 // uint32_t commonEncodingsArrayCount;
301 // uint32_t personalityArraySectionOffset;
302 // uint32_t personalityArrayCount;
303 // uint32_t indexSectionOffset;
304 // uint32_t indexCount;
305
306 m_unwind_header.version = m_unwindinfo_data.GetU32(&offset);
307 m_unwind_header.common_encodings_array_offset = m_unwindinfo_data.GetU32(&offset);
308 m_unwind_header.common_encodings_array_count = m_unwindinfo_data.GetU32(&offset);
309 m_unwind_header.personality_array_offset = m_unwindinfo_data.GetU32(&offset);
310 m_unwind_header.personality_array_count = m_unwindinfo_data.GetU32(&offset);
311 uint32_t indexSectionOffset = m_unwindinfo_data.GetU32(&offset);
312
313 uint32_t indexCount = m_unwindinfo_data.GetU32(&offset);
314
Jason Molendac48ef342015-04-02 04:35:32 +0000315 if (m_unwind_header.common_encodings_array_offset > m_unwindinfo_data.GetByteSize()
316 || m_unwind_header.personality_array_offset > m_unwindinfo_data.GetByteSize()
317 || indexSectionOffset > m_unwindinfo_data.GetByteSize()
318 || offset > m_unwindinfo_data.GetByteSize())
Jason Molendae589e7e2014-12-08 03:09:00 +0000319 {
Jason Molendac48ef342015-04-02 04:35:32 +0000320 Host::SystemLog (Host::eSystemLogError,
321 "error: Invalid offset encountered in compact unwind info, skipping\n");
322 // don't trust anything from this compact_unwind section if it looks
Bruce Mitchenere171da52015-07-22 00:16:02 +0000323 // blatantly invalid data in the header.
Jason Molendae589e7e2014-12-08 03:09:00 +0000324 m_indexes_computed = eLazyBoolNo;
Jason Molendac48ef342015-04-02 04:35:32 +0000325 return;
Jason Molendae589e7e2014-12-08 03:09:00 +0000326 }
327
328 // Parse the basic information from the indexes
329 // We wait to scan the second level page info until it's needed
330
331 // struct unwind_info_section_header_index_entry
332 // {
333 // uint32_t functionOffset;
334 // uint32_t secondLevelPagesSectionOffset;
335 // uint32_t lsdaIndexArraySectionOffset;
336 // };
337
338 offset = indexSectionOffset;
Andy Gibbs3acfe1a2014-12-29 13:03:19 +0000339 for (uint32_t idx = 0; idx < indexCount; idx++)
Jason Molendae589e7e2014-12-08 03:09:00 +0000340 {
341 uint32_t function_offset = m_unwindinfo_data.GetU32(&offset); // functionOffset
342 uint32_t second_level_offset = m_unwindinfo_data.GetU32(&offset); // secondLevelPagesSectionOffset
343 uint32_t lsda_offset = m_unwindinfo_data.GetU32(&offset); // lsdaIndexArraySectionOffset
344
345 if (second_level_offset > m_section_sp->GetByteSize() || lsda_offset > m_section_sp->GetByteSize())
346 {
347 m_indexes_computed = eLazyBoolNo;
348 }
349
350 UnwindIndex this_index;
351 this_index.function_offset = function_offset; //
352 this_index.second_level = second_level_offset;
353 this_index.lsda_array_start = lsda_offset;
354
355 if (m_indexes.size() > 0)
356 {
357 m_indexes[m_indexes.size() - 1].lsda_array_end = lsda_offset;
358 }
359
360 if (second_level_offset == 0)
361 {
362 this_index.sentinal_entry = true;
363 }
364
365 m_indexes.push_back (this_index);
366 }
367 m_indexes_computed = eLazyBoolYes;
368 }
369 else
370 {
371 m_indexes_computed = eLazyBoolNo;
372 }
373}
374
375uint32_t
376CompactUnwindInfo::GetLSDAForFunctionOffset (uint32_t lsda_offset, uint32_t lsda_count, uint32_t function_offset)
377{
378 // struct unwind_info_section_header_lsda_index_entry
379 // {
380 // uint32_t functionOffset;
381 // uint32_t lsdaOffset;
382 // };
383
384 offset_t first_entry = lsda_offset;
385 uint32_t low = 0;
386 uint32_t high = lsda_count;
387 while (low < high)
388 {
389 uint32_t mid = (low + high) / 2;
390 offset_t offset = first_entry + (mid * 8);
391 uint32_t mid_func_offset = m_unwindinfo_data.GetU32(&offset); // functionOffset
392 uint32_t mid_lsda_offset = m_unwindinfo_data.GetU32(&offset); // lsdaOffset
393 if (mid_func_offset == function_offset)
394 {
395 return mid_lsda_offset;
396 }
397 if (mid_func_offset < function_offset)
398 {
399 low = mid + 1;
400 }
401 else
402 {
403 high = mid;
404 }
405 }
406 return 0;
407}
408
409lldb::offset_t
Jason Molenda5c45c542014-12-21 10:44:54 +0000410CompactUnwindInfo::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)
Jason Molendae589e7e2014-12-08 03:09:00 +0000411{
412 // typedef uint32_t compact_unwind_encoding_t;
413 // struct unwind_info_regular_second_level_entry
414 // {
415 // uint32_t functionOffset;
416 // compact_unwind_encoding_t encoding;
417
418 offset_t first_entry = entry_page_offset;
419
420 uint32_t low = 0;
421 uint32_t high = entry_count;
422 uint32_t last = high - 1;
423 while (low < high)
424 {
425 uint32_t mid = (low + high) / 2;
426 offset_t offset = first_entry + (mid * 8);
427 uint32_t mid_func_offset = m_unwindinfo_data.GetU32(&offset); // functionOffset
428 uint32_t next_func_offset = 0;
429 if (mid < last)
430 {
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 {
436 if (mid == last || (next_func_offset > function_offset))
437 {
Jason Molenda5c45c542014-12-21 10:44:54 +0000438 if (entry_func_start_offset)
439 *entry_func_start_offset = mid_func_offset;
440 if (mid != last && entry_func_end_offset)
441 *entry_func_end_offset = next_func_offset;
Jason Molendae589e7e2014-12-08 03:09:00 +0000442 return first_entry + (mid * 8);
443 }
444 else
445 {
446 low = mid + 1;
447 }
448 }
449 else
450 {
451 high = mid;
452 }
453 }
454 return LLDB_INVALID_OFFSET;
455}
456
457uint32_t
Jason Molenda5c45c542014-12-21 10:44:54 +0000458CompactUnwindInfo::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)
Jason Molendae589e7e2014-12-08 03:09:00 +0000459{
460 offset_t first_entry = entry_page_offset;
461
462 uint32_t low = 0;
463 uint32_t high = entry_count;
464 uint32_t last = high - 1;
465 while (low < high)
466 {
467 uint32_t mid = (low + high) / 2;
468 offset_t offset = first_entry + (mid * 4);
469 uint32_t entry = m_unwindinfo_data.GetU32(&offset); // entry
470 uint32_t mid_func_offset = UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET (entry);
471 mid_func_offset += function_offset_base;
472 uint32_t next_func_offset = 0;
473 if (mid < last)
474 {
475 offset = first_entry + ((mid + 1) * 4);
476 uint32_t next_entry = m_unwindinfo_data.GetU32(&offset); // entry
477 next_func_offset = UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET (next_entry);
478 next_func_offset += function_offset_base;
479 }
480 if (mid_func_offset <= function_offset_to_find)
481 {
482 if (mid == last || (next_func_offset > function_offset_to_find))
483 {
Jason Molenda5c45c542014-12-21 10:44:54 +0000484 if (entry_func_start_offset)
485 *entry_func_start_offset = mid_func_offset;
486 if (mid != last && entry_func_end_offset)
487 *entry_func_end_offset = next_func_offset;
Jason Molendae589e7e2014-12-08 03:09:00 +0000488 return UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX (entry);
489 }
490 else
491 {
492 low = mid + 1;
493 }
494 }
495 else
496 {
497 high = mid;
498 }
499 }
500
501 return UINT32_MAX;
502}
503
Jason Molendae589e7e2014-12-08 03:09:00 +0000504bool
505CompactUnwindInfo::GetCompactUnwindInfoForFunction (Target &target, Address address, FunctionInfo &unwind_info)
506{
507 unwind_info.encoding = 0;
508 unwind_info.lsda_address.Clear();
509 unwind_info.personality_ptr_address.Clear();
510
Jason Molendab12a1362014-12-20 03:12:51 +0000511 if (!IsValid (target.GetProcessSP()))
Jason Molendae589e7e2014-12-08 03:09:00 +0000512 return false;
513
Jason Molendae589e7e2014-12-08 03:09:00 +0000514 addr_t text_section_file_address = LLDB_INVALID_ADDRESS;
515 SectionList *sl = m_objfile.GetSectionList ();
516 if (sl)
517 {
518 SectionSP text_sect = sl->FindSectionByType (eSectionTypeCode, true);
519 if (text_sect.get())
520 {
521 text_section_file_address = text_sect->GetFileAddress();
522 }
523 }
524 if (text_section_file_address == LLDB_INVALID_ADDRESS)
525 return false;
526
527 addr_t function_offset = address.GetFileAddress() - m_objfile.GetHeaderAddress().GetFileAddress();
528
529 UnwindIndex key;
530 key.function_offset = function_offset;
531
532 std::vector<UnwindIndex>::const_iterator it;
533 it = std::lower_bound (m_indexes.begin(), m_indexes.end(), key);
534 if (it == m_indexes.end())
535 {
536 return false;
537 }
538
539 if (it->function_offset != key.function_offset)
540 {
541 if (it != m_indexes.begin())
542 --it;
543 }
544
545 if (it->sentinal_entry == true)
546 {
547 return false;
548 }
549
Jason Molenda5c45c542014-12-21 10:44:54 +0000550 auto next_it = it + 1;
Jason Molenda114fb912015-06-18 21:15:58 +0000551 if (next_it != m_indexes.end())
Jason Molenda5c45c542014-12-21 10:44:54 +0000552 {
553 // initialize the function offset end range to be the start of the
554 // next index offset. If we find an entry which is at the end of
555 // the index table, this will establish the range end.
556 unwind_info.valid_range_offset_end = next_it->function_offset;
557 }
558
Jason Molendae589e7e2014-12-08 03:09:00 +0000559 offset_t second_page_offset = it->second_level;
560 offset_t lsda_array_start = it->lsda_array_start;
561 offset_t lsda_array_count = (it->lsda_array_end - it->lsda_array_start) / 8;
562
563 offset_t offset = second_page_offset;
564 uint32_t kind = m_unwindinfo_data.GetU32(&offset); // UNWIND_SECOND_LEVEL_REGULAR or UNWIND_SECOND_LEVEL_COMPRESSED
565
566 if (kind == UNWIND_SECOND_LEVEL_REGULAR)
567 {
568 // struct unwind_info_regular_second_level_page_header
569 // {
570 // uint32_t kind; // UNWIND_SECOND_LEVEL_REGULAR
571 // uint16_t entryPageOffset;
572 // uint16_t entryCount;
573
574 // typedef uint32_t compact_unwind_encoding_t;
575 // struct unwind_info_regular_second_level_entry
576 // {
577 // uint32_t functionOffset;
578 // compact_unwind_encoding_t encoding;
579
580 uint16_t entry_page_offset = m_unwindinfo_data.GetU16(&offset); // entryPageOffset
581 uint16_t entry_count = m_unwindinfo_data.GetU16(&offset); // entryCount
582
Jason Molenda5c45c542014-12-21 10:44:54 +0000583 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);
Jason Molendae589e7e2014-12-08 03:09:00 +0000584 if (entry_offset == LLDB_INVALID_OFFSET)
585 {
586 return false;
587 }
588 entry_offset += 4; // skip over functionOffset
589 unwind_info.encoding = m_unwindinfo_data.GetU32(&entry_offset); // encoding
590 if (unwind_info.encoding & UNWIND_HAS_LSDA)
591 {
592 SectionList *sl = m_objfile.GetSectionList ();
593 if (sl)
594 {
595 uint32_t lsda_offset = GetLSDAForFunctionOffset (lsda_array_start, lsda_array_count, function_offset);
596 addr_t objfile_header_file_address = m_objfile.GetHeaderAddress().GetFileAddress();
597 unwind_info.lsda_address.ResolveAddressUsingFileSections (objfile_header_file_address + lsda_offset, sl);
598 }
599 }
600 if (unwind_info.encoding & UNWIND_PERSONALITY_MASK)
601 {
602 uint32_t personality_index = EXTRACT_BITS (unwind_info.encoding, UNWIND_PERSONALITY_MASK);
603
604 if (personality_index > 0)
605 {
606 personality_index--;
607 if (personality_index < m_unwind_header.personality_array_count)
608 {
609 offset_t offset = m_unwind_header.personality_array_offset;
610 offset += 4 * personality_index;
611 SectionList *sl = m_objfile.GetSectionList ();
612 if (sl)
613 {
614 uint32_t personality_offset = m_unwindinfo_data.GetU32(&offset);
615 addr_t objfile_header_file_address = m_objfile.GetHeaderAddress().GetFileAddress();
616 unwind_info.personality_ptr_address.ResolveAddressUsingFileSections (objfile_header_file_address + personality_offset, sl);
617 }
618 }
619 }
620 }
621 return true;
622 }
623 else if (kind == UNWIND_SECOND_LEVEL_COMPRESSED)
624 {
625 // struct unwind_info_compressed_second_level_page_header
626 // {
627 // uint32_t kind; // UNWIND_SECOND_LEVEL_COMPRESSED
628 // uint16_t entryPageOffset; // offset from this 2nd lvl page idx to array of entries
629 // // (an entry has a function offset and index into the encodings)
630 // // NB function offset from the entry in the compressed page
631 // // must be added to the index's functionOffset value.
632 // uint16_t entryCount;
633 // uint16_t encodingsPageOffset; // offset from this 2nd lvl page idx to array of encodings
634 // uint16_t encodingsCount;
635
636 uint16_t entry_page_offset = m_unwindinfo_data.GetU16(&offset); // entryPageOffset
637 uint16_t entry_count = m_unwindinfo_data.GetU16(&offset); // entryCount
638 uint16_t encodings_page_offset = m_unwindinfo_data.GetU16(&offset); // encodingsPageOffset
639 uint16_t encodings_count = m_unwindinfo_data.GetU16(&offset); // encodingsCount
640
Jason Molenda5c45c542014-12-21 10:44:54 +0000641 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);
Jason Molendae589e7e2014-12-08 03:09:00 +0000642 if (encoding_index == UINT32_MAX || encoding_index >= encodings_count + m_unwind_header.common_encodings_array_count)
643 {
644 return false;
645 }
646 uint32_t encoding = 0;
647 if (encoding_index < m_unwind_header.common_encodings_array_count)
648 {
649 offset = m_unwind_header.common_encodings_array_offset + (encoding_index * sizeof (uint32_t));
650 encoding = m_unwindinfo_data.GetU32(&offset); // encoding entry from the commonEncodingsArray
651 }
652 else
653 {
654 uint32_t page_specific_entry_index = encoding_index - m_unwind_header.common_encodings_array_count;
655 offset = second_page_offset + encodings_page_offset + (page_specific_entry_index * sizeof (uint32_t));
656 encoding = m_unwindinfo_data.GetU32(&offset); // encoding entry from the page-specific encoding array
657 }
658 if (encoding == 0)
659 return false;
Jason Molendae589e7e2014-12-08 03:09:00 +0000660
661 unwind_info.encoding = encoding;
662 if (unwind_info.encoding & UNWIND_HAS_LSDA)
663 {
664 SectionList *sl = m_objfile.GetSectionList ();
665 if (sl)
666 {
667 uint32_t lsda_offset = GetLSDAForFunctionOffset (lsda_array_start, lsda_array_count, function_offset);
668 addr_t objfile_header_file_address = m_objfile.GetHeaderAddress().GetFileAddress();
669 unwind_info.lsda_address.ResolveAddressUsingFileSections (objfile_header_file_address + lsda_offset, sl);
670 }
671 }
672 if (unwind_info.encoding & UNWIND_PERSONALITY_MASK)
673 {
674 uint32_t personality_index = EXTRACT_BITS (unwind_info.encoding, UNWIND_PERSONALITY_MASK);
675
676 if (personality_index > 0)
677 {
678 personality_index--;
679 if (personality_index < m_unwind_header.personality_array_count)
680 {
681 offset_t offset = m_unwind_header.personality_array_offset;
682 offset += 4 * personality_index;
683 SectionList *sl = m_objfile.GetSectionList ();
684 if (sl)
685 {
686 uint32_t personality_offset = m_unwindinfo_data.GetU32(&offset);
687 addr_t objfile_header_file_address = m_objfile.GetHeaderAddress().GetFileAddress();
688 unwind_info.personality_ptr_address.ResolveAddressUsingFileSections (objfile_header_file_address + personality_offset, sl);
689 }
690 }
691 }
692 }
693 return true;
694 }
695 return false;
696}
697
698enum x86_64_eh_regnum {
699 rax = 0,
700 rdx = 1,
701 rcx = 2,
702 rbx = 3,
703 rsi = 4,
704 rdi = 5,
705 rbp = 6,
706 rsp = 7,
707 r8 = 8,
708 r9 = 9,
709 r10 = 10,
710 r11 = 11,
711 r12 = 12,
712 r13 = 13,
713 r14 = 14,
714 r15 = 15,
715 rip = 16 // this is officially the Return Address register number, but close enough
716};
717
718// Convert the compact_unwind_info.h register numbering scheme
Jason Molenda63bd0db2015-09-15 23:20:34 +0000719// to eRegisterKindEHFrame (eh_frame) register numbering scheme.
Jason Molendae589e7e2014-12-08 03:09:00 +0000720uint32_t
721translate_to_eh_frame_regnum_x86_64 (uint32_t unwind_regno)
722{
723 switch (unwind_regno)
724 {
725 case UNWIND_X86_64_REG_RBX:
726 return x86_64_eh_regnum::rbx;
727 case UNWIND_X86_64_REG_R12:
728 return x86_64_eh_regnum::r12;
729 case UNWIND_X86_64_REG_R13:
730 return x86_64_eh_regnum::r13;
731 case UNWIND_X86_64_REG_R14:
732 return x86_64_eh_regnum::r14;
733 case UNWIND_X86_64_REG_R15:
734 return x86_64_eh_regnum::r15;
735 case UNWIND_X86_64_REG_RBP:
736 return x86_64_eh_regnum::rbp;
737 default:
738 return LLDB_INVALID_REGNUM;
739 }
740}
741
742bool
743CompactUnwindInfo::CreateUnwindPlan_x86_64 (Target &target, FunctionInfo &function_info, UnwindPlan &unwind_plan, Address pc_or_function_start)
744{
745 unwind_plan.SetSourceName ("compact unwind info");
746 unwind_plan.SetSourcedFromCompiler (eLazyBoolYes);
747 unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo);
Jason Molendaa18f7072015-08-15 01:21:01 +0000748 unwind_plan.SetRegisterKind (eRegisterKindEHFrame);
Jason Molendae589e7e2014-12-08 03:09:00 +0000749
750 unwind_plan.SetLSDAAddress (function_info.lsda_address);
751 unwind_plan.SetPersonalityFunctionPtr (function_info.personality_ptr_address);
752
753 UnwindPlan::RowSP row (new UnwindPlan::Row);
754
755 const int wordsize = 8;
756 int mode = function_info.encoding & UNWIND_X86_64_MODE_MASK;
757 switch (mode)
758 {
759 case UNWIND_X86_64_MODE_RBP_FRAME:
760 {
Pavel Labathab970f52015-02-23 10:19:16 +0000761 row->GetCFAValue().SetIsRegisterPlusOffset (
762 translate_to_eh_frame_regnum_x86_64 (UNWIND_X86_64_REG_RBP),
763 2 * wordsize);
Jason Molendae589e7e2014-12-08 03:09:00 +0000764 row->SetOffset (0);
765 row->SetRegisterLocationToAtCFAPlusOffset (x86_64_eh_regnum::rbp, wordsize * -2, true);
766 row->SetRegisterLocationToAtCFAPlusOffset (x86_64_eh_regnum::rip, wordsize * -1, true);
767 row->SetRegisterLocationToIsCFAPlusOffset (x86_64_eh_regnum::rsp, 0, true);
768
769 uint32_t saved_registers_offset = EXTRACT_BITS (function_info.encoding, UNWIND_X86_64_RBP_FRAME_OFFSET);
770
771 uint32_t saved_registers_locations = EXTRACT_BITS (function_info.encoding, UNWIND_X86_64_RBP_FRAME_REGISTERS);
772
773 saved_registers_offset += 2;
774
775 for (int i = 0; i < 5; i++)
776 {
777 uint32_t regnum = saved_registers_locations & 0x7;
778 switch (regnum)
779 {
780 case UNWIND_X86_64_REG_NONE:
781 break;
782 case UNWIND_X86_64_REG_RBX:
783 case UNWIND_X86_64_REG_R12:
784 case UNWIND_X86_64_REG_R13:
785 case UNWIND_X86_64_REG_R14:
786 case UNWIND_X86_64_REG_R15:
787 row->SetRegisterLocationToAtCFAPlusOffset (translate_to_eh_frame_regnum_x86_64 (regnum), wordsize * -saved_registers_offset, true);
788 break;
789 }
790 saved_registers_offset--;
791 saved_registers_locations >>= 3;
792 }
793 unwind_plan.AppendRow (row);
794 return true;
795 }
796 break;
797
798 case UNWIND_X86_64_MODE_STACK_IND:
799 {
800 // The clang in Xcode 6 is emitting incorrect compact unwind encodings for this
Jason Molendad99bb0a2015-06-18 22:16:10 +0000801 // style of unwind. It was fixed in llvm r217020.
802 // The clang in Xcode 7 has this fixed.
Jason Molendae589e7e2014-12-08 03:09:00 +0000803 return false;
804 }
805 break;
806
Jason Molendae589e7e2014-12-08 03:09:00 +0000807 case UNWIND_X86_64_MODE_STACK_IMMD:
808 {
Jason Molenda19ba9fb2014-12-22 11:02:02 +0000809 uint32_t stack_size = EXTRACT_BITS (function_info.encoding, UNWIND_X86_64_FRAMELESS_STACK_SIZE);
810 uint32_t register_count = EXTRACT_BITS (function_info.encoding, UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT);
811 uint32_t permutation = EXTRACT_BITS (function_info.encoding, UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION);
Jason Molendae589e7e2014-12-08 03:09:00 +0000812
Jason Molenda19ba9fb2014-12-22 11:02:02 +0000813 if (mode == UNWIND_X86_64_MODE_STACK_IND && function_info.valid_range_offset_start != 0)
Jason Molendae589e7e2014-12-08 03:09:00 +0000814 {
Jason Molenda19ba9fb2014-12-22 11:02:02 +0000815 uint32_t stack_adjust = EXTRACT_BITS (function_info.encoding, UNWIND_X86_64_FRAMELESS_STACK_ADJUST);
Jason Molendae589e7e2014-12-08 03:09:00 +0000816
817 // offset into the function instructions; 0 == beginning of first instruction
Jason Molenda19ba9fb2014-12-22 11:02:02 +0000818 uint32_t offset_to_subl_insn = EXTRACT_BITS (function_info.encoding, UNWIND_X86_64_FRAMELESS_STACK_SIZE);
Jason Molendae589e7e2014-12-08 03:09:00 +0000819
Jason Molenda19ba9fb2014-12-22 11:02:02 +0000820 SectionList *sl = m_objfile.GetSectionList ();
821 if (sl)
822 {
823 ProcessSP process_sp = target.GetProcessSP();
824 if (process_sp)
825 {
826 Address subl_payload_addr (function_info.valid_range_offset_start, sl);
827 subl_payload_addr.Slide (offset_to_subl_insn);
828 Error error;
829 uint64_t large_stack_size = process_sp->ReadUnsignedIntegerFromMemory (subl_payload_addr.GetLoadAddress (&target),
830 4, 0, error);
831 if (large_stack_size != 0 && error.Success ())
832 {
833 // Got the large stack frame size correctly - use it
834 stack_size = large_stack_size + (stack_adjust * wordsize);
835 }
836 else
837 {
838 return false;
839 }
840 }
841 else
842 {
843 return false;
844 }
845 }
846 else
847 {
848 return false;
849 }
Jason Molendae589e7e2014-12-08 03:09:00 +0000850 }
Jason Molendae589e7e2014-12-08 03:09:00 +0000851
Pavel Labathab970f52015-02-23 10:19:16 +0000852 int32_t offset = mode == UNWIND_X86_64_MODE_STACK_IND ? stack_size : stack_size * wordsize;
853 row->GetCFAValue().SetIsRegisterPlusOffset (x86_64_eh_regnum::rsp, offset);
Jason Molenda8122bb02015-01-23 01:02:32 +0000854
Jason Molenda19ba9fb2014-12-22 11:02:02 +0000855 row->SetOffset (0);
856 row->SetRegisterLocationToAtCFAPlusOffset (x86_64_eh_regnum::rip, wordsize * -1, true);
857 row->SetRegisterLocationToIsCFAPlusOffset (x86_64_eh_regnum::rsp, 0, true);
858
859 if (register_count > 0)
Jason Molendae589e7e2014-12-08 03:09:00 +0000860 {
861
862 // We need to include (up to) 6 registers in 10 bits.
863 // That would be 18 bits if we just used 3 bits per reg to indicate
864 // the order they're saved on the stack.
865 //
866 // This is done with Lehmer code permutation, e.g. see
867 // http://stackoverflow.com/questions/1506078/fast-permutation-number-permutation-mapping-algorithms
Jason Molenda9060e982015-05-05 02:05:53 +0000868 int permunreg[6] = {0, 0, 0, 0, 0, 0};
Jason Molendae589e7e2014-12-08 03:09:00 +0000869
870 // This decodes the variable-base number in the 10 bits
871 // and gives us the Lehmer code sequence which can then
872 // be decoded.
873
874 switch (register_count)
875 {
876 case 6:
877 permunreg[0] = permutation/120; // 120 == 5!
878 permutation -= (permunreg[0]*120);
879 permunreg[1] = permutation/24; // 24 == 4!
880 permutation -= (permunreg[1]*24);
881 permunreg[2] = permutation/6; // 6 == 3!
882 permutation -= (permunreg[2]*6);
883 permunreg[3] = permutation/2; // 2 == 2!
884 permutation -= (permunreg[3]*2);
885 permunreg[4] = permutation; // 1 == 1!
886 permunreg[5] = 0;
887 break;
888 case 5:
889 permunreg[0] = permutation/120;
890 permutation -= (permunreg[0]*120);
891 permunreg[1] = permutation/24;
892 permutation -= (permunreg[1]*24);
893 permunreg[2] = permutation/6;
894 permutation -= (permunreg[2]*6);
895 permunreg[3] = permutation/2;
896 permutation -= (permunreg[3]*2);
897 permunreg[4] = permutation;
898 break;
899 case 4:
900 permunreg[0] = permutation/60;
901 permutation -= (permunreg[0]*60);
902 permunreg[1] = permutation/12;
903 permutation -= (permunreg[1]*12);
904 permunreg[2] = permutation/3;
905 permutation -= (permunreg[2]*3);
906 permunreg[3] = permutation;
907 break;
908 case 3:
909 permunreg[0] = permutation/20;
910 permutation -= (permunreg[0]*20);
911 permunreg[1] = permutation/4;
912 permutation -= (permunreg[1]*4);
913 permunreg[2] = permutation;
914 break;
915 case 2:
916 permunreg[0] = permutation/5;
917 permutation -= (permunreg[0]*5);
918 permunreg[1] = permutation;
919 break;
920 case 1:
921 permunreg[0] = permutation;
922 break;
923 }
924
925 // Decode the Lehmer code for this permutation of
926 // the registers v. http://en.wikipedia.org/wiki/Lehmer_code
927
Jason Molenda9060e982015-05-05 02:05:53 +0000928 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 };
Jason Molendae589e7e2014-12-08 03:09:00 +0000929 bool used[7] = { false, false, false, false, false, false, false };
Andy Gibbs3acfe1a2014-12-29 13:03:19 +0000930 for (uint32_t i = 0; i < register_count; i++)
Jason Molendae589e7e2014-12-08 03:09:00 +0000931 {
932 int renum = 0;
933 for (int j = 1; j < 7; j++)
934 {
935 if (used[j] == false)
936 {
937 if (renum == permunreg[i])
938 {
939 registers[i] = j;
940 used[j] = true;
941 break;
942 }
943 renum++;
944 }
945 }
946 }
947
Jason Molendae589e7e2014-12-08 03:09:00 +0000948 uint32_t saved_registers_offset = 1;
Jason Molendae589e7e2014-12-08 03:09:00 +0000949 saved_registers_offset++;
950
951 for (int i = (sizeof (registers) / sizeof (int)) - 1; i >= 0; i--)
952 {
953 switch (registers[i])
954 {
955 case UNWIND_X86_64_REG_NONE:
956 break;
957 case UNWIND_X86_64_REG_RBX:
Jason Molendae589e7e2014-12-08 03:09:00 +0000958 case UNWIND_X86_64_REG_R12:
Jason Molendae589e7e2014-12-08 03:09:00 +0000959 case UNWIND_X86_64_REG_R13:
Jason Molendae589e7e2014-12-08 03:09:00 +0000960 case UNWIND_X86_64_REG_R14:
Jason Molendae589e7e2014-12-08 03:09:00 +0000961 case UNWIND_X86_64_REG_R15:
Jason Molendae589e7e2014-12-08 03:09:00 +0000962 case UNWIND_X86_64_REG_RBP:
Jason Molenda8122bb02015-01-23 01:02:32 +0000963 row->SetRegisterLocationToAtCFAPlusOffset (translate_to_eh_frame_regnum_x86_64 (registers[i]), wordsize * -saved_registers_offset, true);
964 saved_registers_offset++;
Jason Molenda19ba9fb2014-12-22 11:02:02 +0000965 break;
Jason Molendae589e7e2014-12-08 03:09:00 +0000966 }
Jason Molendae589e7e2014-12-08 03:09:00 +0000967 }
Jason Molendae589e7e2014-12-08 03:09:00 +0000968 }
Jason Molenda19ba9fb2014-12-22 11:02:02 +0000969 unwind_plan.AppendRow (row);
970 return true;
Jason Molendae589e7e2014-12-08 03:09:00 +0000971 }
972 break;
Jason Molendae589e7e2014-12-08 03:09:00 +0000973
974 case UNWIND_X86_64_MODE_DWARF:
975 {
976 return false;
977 }
978 break;
979
980 case 0:
981 {
982 return false;
983 }
984 break;
985 }
986 return false;
987}
988
989enum i386_eh_regnum {
990 eax = 0,
991 ecx = 1,
992 edx = 2,
993 ebx = 3,
994 ebp = 4,
995 esp = 5,
996 esi = 6,
997 edi = 7,
998 eip = 8 // this is officially the Return Address register number, but close enough
999};
1000
1001// Convert the compact_unwind_info.h register numbering scheme
Jason Molenda63bd0db2015-09-15 23:20:34 +00001002// to eRegisterKindEHFrame (eh_frame) register numbering scheme.
Jason Molendae589e7e2014-12-08 03:09:00 +00001003uint32_t
1004translate_to_eh_frame_regnum_i386 (uint32_t unwind_regno)
1005{
1006 switch (unwind_regno)
1007 {
1008 case UNWIND_X86_REG_EBX:
1009 return i386_eh_regnum::ebx;
1010 case UNWIND_X86_REG_ECX:
1011 return i386_eh_regnum::ecx;
1012 case UNWIND_X86_REG_EDX:
1013 return i386_eh_regnum::edx;
1014 case UNWIND_X86_REG_EDI:
1015 return i386_eh_regnum::edi;
1016 case UNWIND_X86_REG_ESI:
1017 return i386_eh_regnum::esi;
1018 case UNWIND_X86_REG_EBP:
1019 return i386_eh_regnum::ebp;
1020 default:
1021 return LLDB_INVALID_REGNUM;
1022 }
1023}
1024
1025
1026bool
1027CompactUnwindInfo::CreateUnwindPlan_i386 (Target &target, FunctionInfo &function_info, UnwindPlan &unwind_plan, Address pc_or_function_start)
1028{
1029 unwind_plan.SetSourceName ("compact unwind info");
1030 unwind_plan.SetSourcedFromCompiler (eLazyBoolYes);
1031 unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo);
Jason Molendaa18f7072015-08-15 01:21:01 +00001032 unwind_plan.SetRegisterKind (eRegisterKindEHFrame);
Jason Molendae589e7e2014-12-08 03:09:00 +00001033
1034 unwind_plan.SetLSDAAddress (function_info.lsda_address);
1035 unwind_plan.SetPersonalityFunctionPtr (function_info.personality_ptr_address);
1036
1037 UnwindPlan::RowSP row (new UnwindPlan::Row);
1038
1039 const int wordsize = 4;
1040 int mode = function_info.encoding & UNWIND_X86_MODE_MASK;
1041 switch (mode)
1042 {
1043 case UNWIND_X86_MODE_EBP_FRAME:
1044 {
Pavel Labathab970f52015-02-23 10:19:16 +00001045 row->GetCFAValue().SetIsRegisterPlusOffset (
1046 translate_to_eh_frame_regnum_i386 (UNWIND_X86_REG_EBP), 2 * wordsize);
Jason Molendae589e7e2014-12-08 03:09:00 +00001047 row->SetOffset (0);
1048 row->SetRegisterLocationToAtCFAPlusOffset (i386_eh_regnum::ebp, wordsize * -2, true);
1049 row->SetRegisterLocationToAtCFAPlusOffset (i386_eh_regnum::eip, wordsize * -1, true);
1050 row->SetRegisterLocationToIsCFAPlusOffset (i386_eh_regnum::esp, 0, true);
1051
1052 uint32_t saved_registers_offset = EXTRACT_BITS (function_info.encoding, UNWIND_X86_EBP_FRAME_OFFSET);
1053
1054 uint32_t saved_registers_locations = EXTRACT_BITS (function_info.encoding, UNWIND_X86_EBP_FRAME_REGISTERS);
1055
1056 saved_registers_offset += 2;
1057
1058 for (int i = 0; i < 5; i++)
1059 {
1060 uint32_t regnum = saved_registers_locations & 0x7;
1061 switch (regnum)
1062 {
1063 case UNWIND_X86_REG_NONE:
1064 break;
1065 case UNWIND_X86_REG_EBX:
1066 case UNWIND_X86_REG_ECX:
1067 case UNWIND_X86_REG_EDX:
1068 case UNWIND_X86_REG_EDI:
1069 case UNWIND_X86_REG_ESI:
1070 row->SetRegisterLocationToAtCFAPlusOffset (translate_to_eh_frame_regnum_i386 (regnum), wordsize * -saved_registers_offset, true);
1071 break;
1072 }
1073 saved_registers_offset--;
1074 saved_registers_locations >>= 3;
1075 }
1076 unwind_plan.AppendRow (row);
1077 return true;
1078 }
1079 break;
1080
1081 case UNWIND_X86_MODE_STACK_IND:
1082 case UNWIND_X86_MODE_STACK_IMMD:
Jason Molenda19ba9fb2014-12-22 11:02:02 +00001083 {
1084 uint32_t stack_size = EXTRACT_BITS (function_info.encoding, UNWIND_X86_FRAMELESS_STACK_SIZE);
1085 uint32_t register_count = EXTRACT_BITS (function_info.encoding, UNWIND_X86_FRAMELESS_STACK_REG_COUNT);
1086 uint32_t permutation = EXTRACT_BITS (function_info.encoding, UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION);
1087
1088 if (mode == UNWIND_X86_MODE_STACK_IND && function_info.valid_range_offset_start != 0)
1089 {
1090 uint32_t stack_adjust = EXTRACT_BITS (function_info.encoding, UNWIND_X86_FRAMELESS_STACK_ADJUST);
1091
1092 // offset into the function instructions; 0 == beginning of first instruction
1093 uint32_t offset_to_subl_insn = EXTRACT_BITS (function_info.encoding, UNWIND_X86_FRAMELESS_STACK_SIZE);
1094
1095 SectionList *sl = m_objfile.GetSectionList ();
1096 if (sl)
1097 {
1098 ProcessSP process_sp = target.GetProcessSP();
1099 if (process_sp)
1100 {
1101 Address subl_payload_addr (function_info.valid_range_offset_start, sl);
1102 subl_payload_addr.Slide (offset_to_subl_insn);
1103 Error error;
1104 uint64_t large_stack_size = process_sp->ReadUnsignedIntegerFromMemory (subl_payload_addr.GetLoadAddress (&target),
1105 4, 0, error);
1106 if (large_stack_size != 0 && error.Success ())
1107 {
1108 // Got the large stack frame size correctly - use it
1109 stack_size = large_stack_size + (stack_adjust * wordsize);
1110 }
1111 else
1112 {
1113 return false;
1114 }
1115 }
1116 else
1117 {
1118 return false;
1119 }
1120 }
1121 else
1122 {
1123 return false;
1124 }
1125 }
1126
Pavel Labathab970f52015-02-23 10:19:16 +00001127 int32_t offset = mode == UNWIND_X86_MODE_STACK_IND ? stack_size : stack_size * wordsize;
1128 row->GetCFAValue().SetIsRegisterPlusOffset (i386_eh_regnum::esp, offset);
Jason Molenda19ba9fb2014-12-22 11:02:02 +00001129 row->SetOffset (0);
1130 row->SetRegisterLocationToAtCFAPlusOffset (i386_eh_regnum::eip, wordsize * -1, true);
1131 row->SetRegisterLocationToIsCFAPlusOffset (i386_eh_regnum::esp, 0, true);
1132
1133 if (register_count > 0)
1134 {
1135
1136 // We need to include (up to) 6 registers in 10 bits.
1137 // That would be 18 bits if we just used 3 bits per reg to indicate
1138 // the order they're saved on the stack.
1139 //
1140 // This is done with Lehmer code permutation, e.g. see
1141 // http://stackoverflow.com/questions/1506078/fast-permutation-number-permutation-mapping-algorithms
Jason Molenda9060e982015-05-05 02:05:53 +00001142 int permunreg[6] = {0, 0, 0, 0, 0, 0};
Jason Molenda19ba9fb2014-12-22 11:02:02 +00001143
1144 // This decodes the variable-base number in the 10 bits
1145 // and gives us the Lehmer code sequence which can then
1146 // be decoded.
1147
1148 switch (register_count)
1149 {
1150 case 6:
1151 permunreg[0] = permutation/120; // 120 == 5!
1152 permutation -= (permunreg[0]*120);
1153 permunreg[1] = permutation/24; // 24 == 4!
1154 permutation -= (permunreg[1]*24);
1155 permunreg[2] = permutation/6; // 6 == 3!
1156 permutation -= (permunreg[2]*6);
1157 permunreg[3] = permutation/2; // 2 == 2!
1158 permutation -= (permunreg[3]*2);
1159 permunreg[4] = permutation; // 1 == 1!
1160 permunreg[5] = 0;
1161 break;
1162 case 5:
1163 permunreg[0] = permutation/120;
1164 permutation -= (permunreg[0]*120);
1165 permunreg[1] = permutation/24;
1166 permutation -= (permunreg[1]*24);
1167 permunreg[2] = permutation/6;
1168 permutation -= (permunreg[2]*6);
1169 permunreg[3] = permutation/2;
1170 permutation -= (permunreg[3]*2);
1171 permunreg[4] = permutation;
1172 break;
1173 case 4:
1174 permunreg[0] = permutation/60;
1175 permutation -= (permunreg[0]*60);
1176 permunreg[1] = permutation/12;
1177 permutation -= (permunreg[1]*12);
1178 permunreg[2] = permutation/3;
1179 permutation -= (permunreg[2]*3);
1180 permunreg[3] = permutation;
1181 break;
1182 case 3:
1183 permunreg[0] = permutation/20;
1184 permutation -= (permunreg[0]*20);
1185 permunreg[1] = permutation/4;
1186 permutation -= (permunreg[1]*4);
1187 permunreg[2] = permutation;
1188 break;
1189 case 2:
1190 permunreg[0] = permutation/5;
1191 permutation -= (permunreg[0]*5);
1192 permunreg[1] = permutation;
1193 break;
1194 case 1:
1195 permunreg[0] = permutation;
1196 break;
1197 }
1198
1199 // Decode the Lehmer code for this permutation of
1200 // the registers v. http://en.wikipedia.org/wiki/Lehmer_code
1201
Jason Molenda9060e982015-05-05 02:05:53 +00001202 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 };
Jason Molenda19ba9fb2014-12-22 11:02:02 +00001203 bool used[7] = { false, false, false, false, false, false, false };
Andy Gibbs3acfe1a2014-12-29 13:03:19 +00001204 for (uint32_t i = 0; i < register_count; i++)
Jason Molenda19ba9fb2014-12-22 11:02:02 +00001205 {
1206 int renum = 0;
1207 for (int j = 1; j < 7; j++)
1208 {
1209 if (used[j] == false)
1210 {
1211 if (renum == permunreg[i])
1212 {
1213 registers[i] = j;
1214 used[j] = true;
1215 break;
1216 }
1217 renum++;
1218 }
1219 }
1220 }
1221
1222 uint32_t saved_registers_offset = 1;
1223 saved_registers_offset++;
1224
1225 for (int i = (sizeof (registers) / sizeof (int)) - 1; i >= 0; i--)
1226 {
1227 switch (registers[i])
1228 {
1229 case UNWIND_X86_REG_NONE:
1230 break;
1231 case UNWIND_X86_REG_EBX:
1232 case UNWIND_X86_REG_ECX:
1233 case UNWIND_X86_REG_EDX:
1234 case UNWIND_X86_REG_EDI:
1235 case UNWIND_X86_REG_ESI:
1236 case UNWIND_X86_REG_EBP:
Jason Molenda8122bb02015-01-23 01:02:32 +00001237 row->SetRegisterLocationToAtCFAPlusOffset (translate_to_eh_frame_regnum_i386 (registers[i]), wordsize * -saved_registers_offset, true);
1238 saved_registers_offset++;
Jason Molenda19ba9fb2014-12-22 11:02:02 +00001239 break;
1240 }
Jason Molenda19ba9fb2014-12-22 11:02:02 +00001241 }
1242 }
1243
1244 unwind_plan.AppendRow (row);
1245 return true;
1246 }
1247 break;
1248
Jason Molendae589e7e2014-12-08 03:09:00 +00001249 case UNWIND_X86_MODE_DWARF:
1250 {
1251 return false;
1252 }
1253 break;
1254 }
1255 return false;
1256}
Jason Molendab667c202016-05-25 04:20:28 +00001257
1258
1259
1260// DWARF register numbers from "DWARF for the ARM 64-bit Architecture (AArch64)" doc by ARM
1261
1262enum arm64_eh_regnum {
1263 x19 = 19,
1264 x20 = 20,
1265 x21 = 21,
1266 x22 = 22,
1267 x23 = 23,
1268 x24 = 24,
1269 x25 = 25,
1270 x26 = 26,
1271 x27 = 27,
1272 x28 = 28,
1273
1274 fp = 29,
1275 ra = 30,
1276 sp = 31,
1277 pc = 32,
1278
1279 // Compact unwind encodes d8-d15 but we don't have eh_frame / dwarf reg #'s for the 64-bit
1280 // fp regs. Normally in DWARF it's context sensitive - so it knows it is fetching a
1281 // 32- or 64-bit quantity from reg v8 to indicate s0 or d0 - but the unwinder is operating
1282 // at a lower level and we'd try to fetch 128 bits if we were told that v8 were stored on
1283 // the stack...
1284 v8 = 72,
1285 v9 = 73,
1286 v10 = 74,
1287 v11 = 75,
1288 v12 = 76,
1289 v13 = 77,
1290 v14 = 78,
1291 v15 = 79,
1292};
1293
1294bool
1295CompactUnwindInfo::CreateUnwindPlan_arm64 (Target &target, FunctionInfo &function_info, UnwindPlan &unwind_plan, Address pc_or_function_start)
1296{
1297 unwind_plan.SetSourceName ("compact unwind info");
1298 unwind_plan.SetSourcedFromCompiler (eLazyBoolYes);
1299 unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo);
1300 unwind_plan.SetRegisterKind (eRegisterKindEHFrame);
1301
1302 unwind_plan.SetLSDAAddress (function_info.lsda_address);
1303 unwind_plan.SetPersonalityFunctionPtr (function_info.personality_ptr_address);
1304
1305 UnwindPlan::RowSP row (new UnwindPlan::Row);
1306
1307 const int wordsize = 8;
1308 int mode = function_info.encoding & UNWIND_ARM64_MODE_MASK;
1309
1310 if (mode == UNWIND_ARM64_MODE_DWARF)
1311 return false;
1312
1313 if (mode == UNWIND_ARM64_MODE_FRAMELESS)
1314 {
1315 row->SetOffset (0);
1316
1317 uint32_t stack_size = (EXTRACT_BITS (function_info.encoding, UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK)) * 16;
1318
1319 // Our previous Call Frame Address is the stack pointer plus the stack size
1320 row->GetCFAValue().SetIsRegisterPlusOffset (arm64_eh_regnum::sp, stack_size);
1321
1322 // Our previous PC is in the LR
1323 row->SetRegisterLocationToRegister(arm64_eh_regnum::pc, arm64_eh_regnum::ra, true);
1324
1325 unwind_plan.AppendRow (row);
1326 return true;
1327 }
1328
1329 // Should not be possible
1330 if (mode != UNWIND_ARM64_MODE_FRAME)
1331 return false;
1332
1333
1334 // mode == UNWIND_ARM64_MODE_FRAME
1335
1336 row->GetCFAValue().SetIsRegisterPlusOffset (arm64_eh_regnum::fp , 2 * wordsize);
1337 row->SetOffset (0);
1338 row->SetRegisterLocationToAtCFAPlusOffset (arm64_eh_regnum::fp, wordsize * -2, true);
1339 row->SetRegisterLocationToAtCFAPlusOffset (arm64_eh_regnum::pc, wordsize * -1, true);
1340 row->SetRegisterLocationToIsCFAPlusOffset (arm64_eh_regnum::sp, 0, true);
1341
1342 int reg_pairs_saved_count = 1;
1343
1344 uint32_t saved_register_bits = function_info.encoding & 0xfff;
1345
1346 if (saved_register_bits & UNWIND_ARM64_FRAME_X19_X20_PAIR)
1347 {
1348 int cfa_offset = reg_pairs_saved_count * -2 * wordsize;
1349 cfa_offset -= wordsize;
1350 row->SetRegisterLocationToAtCFAPlusOffset (arm64_eh_regnum::x19, cfa_offset, true);
1351 cfa_offset -= wordsize;
1352 row->SetRegisterLocationToAtCFAPlusOffset (arm64_eh_regnum::x20, cfa_offset, true);
1353 reg_pairs_saved_count++;
1354 }
1355
1356 if (saved_register_bits & UNWIND_ARM64_FRAME_X21_X22_PAIR)
1357 {
1358 int cfa_offset = reg_pairs_saved_count * -2 * wordsize;
1359 cfa_offset -= wordsize;
1360 row->SetRegisterLocationToAtCFAPlusOffset (arm64_eh_regnum::x21, cfa_offset, true);
1361 cfa_offset -= wordsize;
1362 row->SetRegisterLocationToAtCFAPlusOffset (arm64_eh_regnum::x22, cfa_offset, true);
1363 reg_pairs_saved_count++;
1364 }
1365
1366 if (saved_register_bits & UNWIND_ARM64_FRAME_X23_X24_PAIR)
1367 {
1368 int cfa_offset = reg_pairs_saved_count * -2 * wordsize;
1369 cfa_offset -= wordsize;
1370 row->SetRegisterLocationToAtCFAPlusOffset (arm64_eh_regnum::x23, cfa_offset, true);
1371 cfa_offset -= wordsize;
1372 row->SetRegisterLocationToAtCFAPlusOffset (arm64_eh_regnum::x24, cfa_offset, true);
1373 reg_pairs_saved_count++;
1374 }
1375
1376 if (saved_register_bits & UNWIND_ARM64_FRAME_X25_X26_PAIR)
1377 {
1378 int cfa_offset = reg_pairs_saved_count * -2 * wordsize;
1379 cfa_offset -= wordsize;
1380 row->SetRegisterLocationToAtCFAPlusOffset (arm64_eh_regnum::x25, cfa_offset, true);
1381 cfa_offset -= wordsize;
1382 row->SetRegisterLocationToAtCFAPlusOffset (arm64_eh_regnum::x26, cfa_offset, true);
1383 reg_pairs_saved_count++;
1384 }
1385
1386 if (saved_register_bits & UNWIND_ARM64_FRAME_X27_X28_PAIR)
1387 {
1388 int cfa_offset = reg_pairs_saved_count * -2 * wordsize;
1389 cfa_offset -= wordsize;
1390 row->SetRegisterLocationToAtCFAPlusOffset (arm64_eh_regnum::x27, cfa_offset, true);
1391 cfa_offset -= wordsize;
1392 row->SetRegisterLocationToAtCFAPlusOffset (arm64_eh_regnum::x28, cfa_offset, true);
1393 reg_pairs_saved_count++;
1394 }
1395
1396 // If we use the v8-v15 regnums here, the unwinder will try to grab 128 bits off the stack;
1397 // not sure if we have a good way to represent the 64-bitness of these saves.
1398
1399 if (saved_register_bits & UNWIND_ARM64_FRAME_D8_D9_PAIR)
1400 {
1401 reg_pairs_saved_count++;
1402 }
1403 if (saved_register_bits & UNWIND_ARM64_FRAME_D10_D11_PAIR)
1404 {
1405 reg_pairs_saved_count++;
1406 }
1407 if (saved_register_bits & UNWIND_ARM64_FRAME_D12_D13_PAIR)
1408 {
1409 reg_pairs_saved_count++;
1410 }
1411 if (saved_register_bits & UNWIND_ARM64_FRAME_D14_D15_PAIR)
1412 {
1413 reg_pairs_saved_count++;
1414 }
1415
1416 unwind_plan.AppendRow (row);
1417 return true;
1418}
1419