CompactUnwindInfo.cpp revision 278332
1278332Semaste//===-- CompactUnwindInfo.cpp -----------------------------------*- C++ -*-===// 2278332Semaste// 3278332Semaste// The LLVM Compiler Infrastructure 4278332Semaste// 5278332Semaste// This file is distributed under the University of Illinois Open Source 6278332Semaste// License. See LICENSE.TXT for details. 7278332Semaste// 8278332Semaste//===----------------------------------------------------------------------===// 9278332Semaste 10278332Semaste 11278332Semaste// C Includes 12278332Semaste// C++ Includes 13278332Semaste#include <algorithm> 14278332Semaste 15278332Semaste#include "lldb/Core/ArchSpec.h" 16278332Semaste#include "lldb/Core/Log.h" 17278332Semaste#include "lldb/Core/Module.h" 18278332Semaste#include "lldb/Core/Section.h" 19278332Semaste#include "lldb/Core/Section.h" 20278332Semaste#include "lldb/Core/StreamString.h" 21278332Semaste#include "lldb/Symbol/CompactUnwindInfo.h" 22278332Semaste#include "lldb/Symbol/ObjectFile.h" 23278332Semaste#include "lldb/Symbol/UnwindPlan.h" 24278332Semaste#include "lldb/Target/Process.h" 25278332Semaste#include "lldb/Target/Target.h" 26278332Semaste 27278332Semaste#include "llvm/Support/MathExtras.h" 28278332Semaste 29278332Semasteusing namespace lldb; 30278332Semasteusing namespace lldb_private; 31278332Semaste 32278332Semaste 33278332Semastenamespace lldb_private { 34278332Semaste 35278332Semaste // Constants from <mach-o/compact_unwind_encoding.h> 36278332Semaste 37278332Semaste enum { 38278332Semaste UNWIND_IS_NOT_FUNCTION_START = 0x80000000, 39278332Semaste UNWIND_HAS_LSDA = 0x40000000, 40278332Semaste UNWIND_PERSONALITY_MASK = 0x30000000, 41278332Semaste }; 42278332Semaste 43278332Semaste enum { 44278332Semaste UNWIND_X86_MODE_MASK = 0x0F000000, 45278332Semaste UNWIND_X86_MODE_EBP_FRAME = 0x01000000, 46278332Semaste UNWIND_X86_MODE_STACK_IMMD = 0x02000000, 47278332Semaste UNWIND_X86_MODE_STACK_IND = 0x03000000, 48278332Semaste UNWIND_X86_MODE_DWARF = 0x04000000, 49278332Semaste 50278332Semaste UNWIND_X86_EBP_FRAME_REGISTERS = 0x00007FFF, 51278332Semaste UNWIND_X86_EBP_FRAME_OFFSET = 0x00FF0000, 52278332Semaste 53278332Semaste UNWIND_X86_FRAMELESS_STACK_SIZE = 0x00FF0000, 54278332Semaste UNWIND_X86_FRAMELESS_STACK_ADJUST = 0x0000E000, 55278332Semaste UNWIND_X86_FRAMELESS_STACK_REG_COUNT = 0x00001C00, 56278332Semaste UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION = 0x000003FF, 57278332Semaste 58278332Semaste UNWIND_X86_DWARF_SECTION_OFFSET = 0x00FFFFFF, 59278332Semaste }; 60278332Semaste 61278332Semaste enum { 62278332Semaste UNWIND_X86_REG_NONE = 0, 63278332Semaste UNWIND_X86_REG_EBX = 1, 64278332Semaste UNWIND_X86_REG_ECX = 2, 65278332Semaste UNWIND_X86_REG_EDX = 3, 66278332Semaste UNWIND_X86_REG_EDI = 4, 67278332Semaste UNWIND_X86_REG_ESI = 5, 68278332Semaste UNWIND_X86_REG_EBP = 6, 69278332Semaste }; 70278332Semaste enum { 71278332Semaste UNWIND_X86_64_MODE_MASK = 0x0F000000, 72278332Semaste UNWIND_X86_64_MODE_RBP_FRAME = 0x01000000, 73278332Semaste UNWIND_X86_64_MODE_STACK_IMMD = 0x02000000, 74278332Semaste UNWIND_X86_64_MODE_STACK_IND = 0x03000000, 75278332Semaste UNWIND_X86_64_MODE_DWARF = 0x04000000, 76278332Semaste 77278332Semaste UNWIND_X86_64_RBP_FRAME_REGISTERS = 0x00007FFF, 78278332Semaste UNWIND_X86_64_RBP_FRAME_OFFSET = 0x00FF0000, 79278332Semaste 80278332Semaste UNWIND_X86_64_FRAMELESS_STACK_SIZE = 0x00FF0000, 81278332Semaste UNWIND_X86_64_FRAMELESS_STACK_ADJUST = 0x0000E000, 82278332Semaste UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT = 0x00001C00, 83278332Semaste UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION = 0x000003FF, 84278332Semaste 85278332Semaste UNWIND_X86_64_DWARF_SECTION_OFFSET = 0x00FFFFFF, 86278332Semaste }; 87278332Semaste 88278332Semaste enum { 89278332Semaste UNWIND_X86_64_REG_NONE = 0, 90278332Semaste UNWIND_X86_64_REG_RBX = 1, 91278332Semaste UNWIND_X86_64_REG_R12 = 2, 92278332Semaste UNWIND_X86_64_REG_R13 = 3, 93278332Semaste UNWIND_X86_64_REG_R14 = 4, 94278332Semaste UNWIND_X86_64_REG_R15 = 5, 95278332Semaste UNWIND_X86_64_REG_RBP = 6, 96278332Semaste }; 97278332Semaste}; 98278332Semaste 99278332Semaste 100278332Semaste#ifndef UNWIND_SECOND_LEVEL_REGULAR 101278332Semaste#define UNWIND_SECOND_LEVEL_REGULAR 2 102278332Semaste#endif 103278332Semaste 104278332Semaste#ifndef UNWIND_SECOND_LEVEL_COMPRESSED 105278332Semaste#define UNWIND_SECOND_LEVEL_COMPRESSED 3 106278332Semaste#endif 107278332Semaste 108278332Semaste#ifndef UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET 109278332Semaste#define UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET(entry) (entry & 0x00FFFFFF) 110278332Semaste#endif 111278332Semaste 112278332Semaste#ifndef UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX 113278332Semaste#define UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX(entry) ((entry >> 24) & 0xFF) 114278332Semaste#endif 115278332Semaste 116278332Semaste#define EXTRACT_BITS(value, mask) \ 117278332Semaste ( (value >> llvm::countTrailingZeros(static_cast<uint32_t>(mask), llvm::ZB_Width)) & \ 118278332Semaste (((1 << llvm::CountPopulation_32(static_cast<uint32_t>(mask))))-1) ) 119278332Semaste 120278332Semaste 121278332Semaste 122278332Semaste//---------------------- 123278332Semaste// constructor 124278332Semaste//---------------------- 125278332Semaste 126278332Semaste 127278332SemasteCompactUnwindInfo::CompactUnwindInfo(ObjectFile& objfile, SectionSP& section_sp) : 128278332Semaste m_objfile (objfile), 129278332Semaste m_section_sp (section_sp), 130278332Semaste m_section_contents_if_encrypted (), 131278332Semaste m_mutex (), 132278332Semaste m_indexes (), 133278332Semaste m_indexes_computed (eLazyBoolCalculate), 134278332Semaste m_unwindinfo_data (), 135278332Semaste m_unwindinfo_data_computed (false), 136278332Semaste m_unwind_header () 137278332Semaste{ 138278332Semaste 139278332Semaste} 140278332Semaste 141278332Semaste//---------------------- 142278332Semaste// destructor 143278332Semaste//---------------------- 144278332Semaste 145278332SemasteCompactUnwindInfo::~CompactUnwindInfo() 146278332Semaste{ 147278332Semaste} 148278332Semaste 149278332Semastebool 150278332SemasteCompactUnwindInfo::GetUnwindPlan (Target &target, Address addr, UnwindPlan& unwind_plan) 151278332Semaste{ 152278332Semaste if (!IsValid (target.GetProcessSP())) 153278332Semaste { 154278332Semaste return false; 155278332Semaste } 156278332Semaste FunctionInfo function_info; 157278332Semaste if (GetCompactUnwindInfoForFunction (target, addr, function_info)) 158278332Semaste { 159278332Semaste // shortcut return for functions that have no compact unwind 160278332Semaste if (function_info.encoding == 0) 161278332Semaste return false; 162278332Semaste 163278332Semaste ArchSpec arch; 164278332Semaste if (m_objfile.GetArchitecture (arch)) 165278332Semaste { 166278332Semaste 167278332Semaste Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND)); 168278332Semaste if (log && log->GetVerbose()) 169278332Semaste { 170278332Semaste StreamString strm; 171278332Semaste addr.Dump (&strm, NULL, Address::DumpStyle::DumpStyleResolvedDescriptionNoFunctionArguments, Address::DumpStyle::DumpStyleFileAddress, arch.GetAddressByteSize()); 172278332Semaste log->Printf ("Got compact unwind encoding 0x%x for function %s", function_info.encoding, strm.GetData()); 173278332Semaste } 174278332Semaste 175278332Semaste if (function_info.valid_range_offset_start != 0 && function_info.valid_range_offset_end != 0) 176278332Semaste { 177278332Semaste SectionList *sl = m_objfile.GetSectionList (); 178278332Semaste if (sl) 179278332Semaste { 180278332Semaste addr_t func_range_start_file_addr = 181278332Semaste function_info.valid_range_offset_start + m_objfile.GetHeaderAddress().GetFileAddress(); 182278332Semaste AddressRange func_range (func_range_start_file_addr, 183278332Semaste function_info.valid_range_offset_end - function_info.valid_range_offset_start, 184278332Semaste sl); 185278332Semaste unwind_plan.SetPlanValidAddressRange (func_range); 186278332Semaste } 187278332Semaste } 188278332Semaste 189278332Semaste if (arch.GetTriple().getArch() == llvm::Triple::x86_64) 190278332Semaste { 191278332Semaste return CreateUnwindPlan_x86_64 (target, function_info, unwind_plan, addr); 192278332Semaste } 193278332Semaste if (arch.GetTriple().getArch() == llvm::Triple::x86) 194278332Semaste { 195278332Semaste return CreateUnwindPlan_i386 (target, function_info, unwind_plan, addr); 196278332Semaste } 197278332Semaste } 198278332Semaste } 199278332Semaste return false; 200278332Semaste} 201278332Semaste 202278332Semastebool 203278332SemasteCompactUnwindInfo::IsValid (const ProcessSP &process_sp) 204278332Semaste{ 205278332Semaste if (m_section_sp.get() == nullptr) 206278332Semaste return false; 207278332Semaste 208278332Semaste if (m_indexes_computed == eLazyBoolYes && m_unwindinfo_data_computed) 209278332Semaste return true; 210278332Semaste 211278332Semaste ScanIndex (process_sp); 212278332Semaste 213278332Semaste return m_indexes_computed == eLazyBoolYes && m_unwindinfo_data_computed; 214278332Semaste} 215278332Semaste 216278332Semastevoid 217278332SemasteCompactUnwindInfo::ScanIndex (const ProcessSP &process_sp) 218278332Semaste{ 219278332Semaste Mutex::Locker locker(m_mutex); 220278332Semaste if (m_indexes_computed == eLazyBoolYes && m_unwindinfo_data_computed) 221278332Semaste return; 222278332Semaste 223278332Semaste // We can't read the index for some reason. 224278332Semaste if (m_indexes_computed == eLazyBoolNo) 225278332Semaste { 226278332Semaste return; 227278332Semaste } 228278332Semaste 229278332Semaste Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND)); 230278332Semaste if (log) 231278332Semaste m_objfile.GetModule()->LogMessage(log, "Reading compact unwind first-level indexes"); 232278332Semaste 233278332Semaste if (m_unwindinfo_data_computed == false) 234278332Semaste { 235278332Semaste if (m_section_sp->IsEncrypted()) 236278332Semaste { 237278332Semaste // Can't get section contents of a protected/encrypted section until we have a live 238278332Semaste // process and can read them out of memory. 239278332Semaste if (process_sp.get() == nullptr) 240278332Semaste return; 241278332Semaste m_section_contents_if_encrypted.reset (new DataBufferHeap (m_section_sp->GetByteSize(), 0)); 242278332Semaste Error error; 243278332Semaste if (process_sp->ReadMemory ( 244278332Semaste m_section_sp->GetLoadBaseAddress (&process_sp->GetTarget()), 245278332Semaste m_section_contents_if_encrypted->GetBytes(), 246278332Semaste m_section_sp->GetByteSize(), error) == m_section_sp->GetByteSize() && error.Success()) 247278332Semaste { 248278332Semaste m_unwindinfo_data.SetAddressByteSize (process_sp->GetTarget().GetArchitecture().GetAddressByteSize()); 249278332Semaste m_unwindinfo_data.SetByteOrder (process_sp->GetTarget().GetArchitecture().GetByteOrder()); 250278332Semaste m_unwindinfo_data.SetData (m_section_contents_if_encrypted, 0); 251278332Semaste } 252278332Semaste } 253278332Semaste else 254278332Semaste { 255278332Semaste m_objfile.ReadSectionData (m_section_sp.get(), m_unwindinfo_data); 256278332Semaste } 257278332Semaste if (m_unwindinfo_data.GetByteSize() != m_section_sp->GetByteSize()) 258278332Semaste return; 259278332Semaste m_unwindinfo_data_computed = true; 260278332Semaste } 261278332Semaste 262278332Semaste if (m_unwindinfo_data.GetByteSize() > 0) 263278332Semaste { 264278332Semaste offset_t offset = 0; 265278332Semaste 266278332Semaste // struct unwind_info_section_header 267278332Semaste // { 268278332Semaste // uint32_t version; // UNWIND_SECTION_VERSION 269278332Semaste // uint32_t commonEncodingsArraySectionOffset; 270278332Semaste // uint32_t commonEncodingsArrayCount; 271278332Semaste // uint32_t personalityArraySectionOffset; 272278332Semaste // uint32_t personalityArrayCount; 273278332Semaste // uint32_t indexSectionOffset; 274278332Semaste // uint32_t indexCount; 275278332Semaste 276278332Semaste m_unwind_header.version = m_unwindinfo_data.GetU32(&offset); 277278332Semaste m_unwind_header.common_encodings_array_offset = m_unwindinfo_data.GetU32(&offset); 278278332Semaste m_unwind_header.common_encodings_array_count = m_unwindinfo_data.GetU32(&offset); 279278332Semaste m_unwind_header.personality_array_offset = m_unwindinfo_data.GetU32(&offset); 280278332Semaste m_unwind_header.personality_array_count = m_unwindinfo_data.GetU32(&offset); 281278332Semaste uint32_t indexSectionOffset = m_unwindinfo_data.GetU32(&offset); 282278332Semaste 283278332Semaste uint32_t indexCount = m_unwindinfo_data.GetU32(&offset); 284278332Semaste 285278332Semaste if (m_unwind_header.version != 1) 286278332Semaste { 287278332Semaste m_indexes_computed = eLazyBoolNo; 288278332Semaste } 289278332Semaste 290278332Semaste // Parse the basic information from the indexes 291278332Semaste // We wait to scan the second level page info until it's needed 292278332Semaste 293278332Semaste // struct unwind_info_section_header_index_entry 294278332Semaste // { 295278332Semaste // uint32_t functionOffset; 296278332Semaste // uint32_t secondLevelPagesSectionOffset; 297278332Semaste // uint32_t lsdaIndexArraySectionOffset; 298278332Semaste // }; 299278332Semaste 300278332Semaste offset = indexSectionOffset; 301278332Semaste for (uint32_t idx = 0; idx < indexCount; idx++) 302278332Semaste { 303278332Semaste uint32_t function_offset = m_unwindinfo_data.GetU32(&offset); // functionOffset 304278332Semaste uint32_t second_level_offset = m_unwindinfo_data.GetU32(&offset); // secondLevelPagesSectionOffset 305278332Semaste uint32_t lsda_offset = m_unwindinfo_data.GetU32(&offset); // lsdaIndexArraySectionOffset 306278332Semaste 307278332Semaste if (second_level_offset > m_section_sp->GetByteSize() || lsda_offset > m_section_sp->GetByteSize()) 308278332Semaste { 309278332Semaste m_indexes_computed = eLazyBoolNo; 310278332Semaste } 311278332Semaste 312278332Semaste UnwindIndex this_index; 313278332Semaste this_index.function_offset = function_offset; // 314278332Semaste this_index.second_level = second_level_offset; 315278332Semaste this_index.lsda_array_start = lsda_offset; 316278332Semaste 317278332Semaste if (m_indexes.size() > 0) 318278332Semaste { 319278332Semaste m_indexes[m_indexes.size() - 1].lsda_array_end = lsda_offset; 320278332Semaste } 321278332Semaste 322278332Semaste if (second_level_offset == 0) 323278332Semaste { 324278332Semaste this_index.sentinal_entry = true; 325278332Semaste } 326278332Semaste 327278332Semaste m_indexes.push_back (this_index); 328278332Semaste } 329278332Semaste m_indexes_computed = eLazyBoolYes; 330278332Semaste } 331278332Semaste else 332278332Semaste { 333278332Semaste m_indexes_computed = eLazyBoolNo; 334278332Semaste } 335278332Semaste} 336278332Semaste 337278332Semasteuint32_t 338278332SemasteCompactUnwindInfo::GetLSDAForFunctionOffset (uint32_t lsda_offset, uint32_t lsda_count, uint32_t function_offset) 339278332Semaste{ 340278332Semaste // struct unwind_info_section_header_lsda_index_entry 341278332Semaste // { 342278332Semaste // uint32_t functionOffset; 343278332Semaste // uint32_t lsdaOffset; 344278332Semaste // }; 345278332Semaste 346278332Semaste offset_t first_entry = lsda_offset; 347278332Semaste uint32_t low = 0; 348278332Semaste uint32_t high = lsda_count; 349278332Semaste while (low < high) 350278332Semaste { 351278332Semaste uint32_t mid = (low + high) / 2; 352278332Semaste offset_t offset = first_entry + (mid * 8); 353278332Semaste uint32_t mid_func_offset = m_unwindinfo_data.GetU32(&offset); // functionOffset 354278332Semaste uint32_t mid_lsda_offset = m_unwindinfo_data.GetU32(&offset); // lsdaOffset 355278332Semaste if (mid_func_offset == function_offset) 356278332Semaste { 357278332Semaste return mid_lsda_offset; 358278332Semaste } 359278332Semaste if (mid_func_offset < function_offset) 360278332Semaste { 361278332Semaste low = mid + 1; 362278332Semaste } 363278332Semaste else 364278332Semaste { 365278332Semaste high = mid; 366278332Semaste } 367278332Semaste } 368278332Semaste return 0; 369278332Semaste} 370278332Semaste 371278332Semastelldb::offset_t 372278332SemasteCompactUnwindInfo::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) 373278332Semaste{ 374278332Semaste // typedef uint32_t compact_unwind_encoding_t; 375278332Semaste // struct unwind_info_regular_second_level_entry 376278332Semaste // { 377278332Semaste // uint32_t functionOffset; 378278332Semaste // compact_unwind_encoding_t encoding; 379278332Semaste 380278332Semaste offset_t first_entry = entry_page_offset; 381278332Semaste 382278332Semaste uint32_t low = 0; 383278332Semaste uint32_t high = entry_count; 384278332Semaste uint32_t last = high - 1; 385278332Semaste while (low < high) 386278332Semaste { 387278332Semaste uint32_t mid = (low + high) / 2; 388278332Semaste offset_t offset = first_entry + (mid * 8); 389278332Semaste uint32_t mid_func_offset = m_unwindinfo_data.GetU32(&offset); // functionOffset 390278332Semaste uint32_t next_func_offset = 0; 391278332Semaste if (mid < last) 392278332Semaste { 393278332Semaste offset = first_entry + ((mid + 1) * 8); 394278332Semaste next_func_offset = m_unwindinfo_data.GetU32(&offset); // functionOffset 395278332Semaste } 396278332Semaste if (mid_func_offset <= function_offset) 397278332Semaste { 398278332Semaste if (mid == last || (next_func_offset > function_offset)) 399278332Semaste { 400278332Semaste if (entry_func_start_offset) 401278332Semaste *entry_func_start_offset = mid_func_offset; 402278332Semaste if (mid != last && entry_func_end_offset) 403278332Semaste *entry_func_end_offset = next_func_offset; 404278332Semaste return first_entry + (mid * 8); 405278332Semaste } 406278332Semaste else 407278332Semaste { 408278332Semaste low = mid + 1; 409278332Semaste } 410278332Semaste } 411278332Semaste else 412278332Semaste { 413278332Semaste high = mid; 414278332Semaste } 415278332Semaste } 416278332Semaste return LLDB_INVALID_OFFSET; 417278332Semaste} 418278332Semaste 419278332Semasteuint32_t 420278332SemasteCompactUnwindInfo::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) 421278332Semaste{ 422278332Semaste offset_t first_entry = entry_page_offset; 423278332Semaste 424278332Semaste uint32_t low = 0; 425278332Semaste uint32_t high = entry_count; 426278332Semaste uint32_t last = high - 1; 427278332Semaste while (low < high) 428278332Semaste { 429278332Semaste uint32_t mid = (low + high) / 2; 430278332Semaste offset_t offset = first_entry + (mid * 4); 431278332Semaste uint32_t entry = m_unwindinfo_data.GetU32(&offset); // entry 432278332Semaste uint32_t mid_func_offset = UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET (entry); 433278332Semaste mid_func_offset += function_offset_base; 434278332Semaste uint32_t next_func_offset = 0; 435278332Semaste if (mid < last) 436278332Semaste { 437278332Semaste offset = first_entry + ((mid + 1) * 4); 438278332Semaste uint32_t next_entry = m_unwindinfo_data.GetU32(&offset); // entry 439278332Semaste next_func_offset = UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET (next_entry); 440278332Semaste next_func_offset += function_offset_base; 441278332Semaste } 442278332Semaste if (mid_func_offset <= function_offset_to_find) 443278332Semaste { 444278332Semaste if (mid == last || (next_func_offset > function_offset_to_find)) 445278332Semaste { 446278332Semaste if (entry_func_start_offset) 447278332Semaste *entry_func_start_offset = mid_func_offset; 448278332Semaste if (mid != last && entry_func_end_offset) 449278332Semaste *entry_func_end_offset = next_func_offset; 450278332Semaste return UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX (entry); 451278332Semaste } 452278332Semaste else 453278332Semaste { 454278332Semaste low = mid + 1; 455278332Semaste } 456278332Semaste } 457278332Semaste else 458278332Semaste { 459278332Semaste high = mid; 460278332Semaste } 461278332Semaste } 462278332Semaste 463278332Semaste return UINT32_MAX; 464278332Semaste} 465278332Semaste 466278332Semastebool 467278332SemasteCompactUnwindInfo::GetCompactUnwindInfoForFunction (Target &target, Address address, FunctionInfo &unwind_info) 468278332Semaste{ 469278332Semaste unwind_info.encoding = 0; 470278332Semaste unwind_info.lsda_address.Clear(); 471278332Semaste unwind_info.personality_ptr_address.Clear(); 472278332Semaste 473278332Semaste if (!IsValid (target.GetProcessSP())) 474278332Semaste return false; 475278332Semaste 476278332Semaste addr_t text_section_file_address = LLDB_INVALID_ADDRESS; 477278332Semaste SectionList *sl = m_objfile.GetSectionList (); 478278332Semaste if (sl) 479278332Semaste { 480278332Semaste SectionSP text_sect = sl->FindSectionByType (eSectionTypeCode, true); 481278332Semaste if (text_sect.get()) 482278332Semaste { 483278332Semaste text_section_file_address = text_sect->GetFileAddress(); 484278332Semaste } 485278332Semaste } 486278332Semaste if (text_section_file_address == LLDB_INVALID_ADDRESS) 487278332Semaste return false; 488278332Semaste 489278332Semaste addr_t function_offset = address.GetFileAddress() - m_objfile.GetHeaderAddress().GetFileAddress(); 490278332Semaste 491278332Semaste UnwindIndex key; 492278332Semaste key.function_offset = function_offset; 493278332Semaste 494278332Semaste std::vector<UnwindIndex>::const_iterator it; 495278332Semaste it = std::lower_bound (m_indexes.begin(), m_indexes.end(), key); 496278332Semaste if (it == m_indexes.end()) 497278332Semaste { 498278332Semaste return false; 499278332Semaste } 500278332Semaste 501278332Semaste if (it->function_offset != key.function_offset) 502278332Semaste { 503278332Semaste if (it != m_indexes.begin()) 504278332Semaste --it; 505278332Semaste } 506278332Semaste 507278332Semaste if (it->sentinal_entry == true) 508278332Semaste { 509278332Semaste return false; 510278332Semaste } 511278332Semaste 512278332Semaste auto next_it = it + 1; 513278332Semaste if (next_it != m_indexes.begin()) 514278332Semaste { 515278332Semaste // initialize the function offset end range to be the start of the 516278332Semaste // next index offset. If we find an entry which is at the end of 517278332Semaste // the index table, this will establish the range end. 518278332Semaste unwind_info.valid_range_offset_end = next_it->function_offset; 519278332Semaste } 520278332Semaste 521278332Semaste offset_t second_page_offset = it->second_level; 522278332Semaste offset_t lsda_array_start = it->lsda_array_start; 523278332Semaste offset_t lsda_array_count = (it->lsda_array_end - it->lsda_array_start) / 8; 524278332Semaste 525278332Semaste offset_t offset = second_page_offset; 526278332Semaste uint32_t kind = m_unwindinfo_data.GetU32(&offset); // UNWIND_SECOND_LEVEL_REGULAR or UNWIND_SECOND_LEVEL_COMPRESSED 527278332Semaste 528278332Semaste if (kind == UNWIND_SECOND_LEVEL_REGULAR) 529278332Semaste { 530278332Semaste // struct unwind_info_regular_second_level_page_header 531278332Semaste // { 532278332Semaste // uint32_t kind; // UNWIND_SECOND_LEVEL_REGULAR 533278332Semaste // uint16_t entryPageOffset; 534278332Semaste // uint16_t entryCount; 535278332Semaste 536278332Semaste // typedef uint32_t compact_unwind_encoding_t; 537278332Semaste // struct unwind_info_regular_second_level_entry 538278332Semaste // { 539278332Semaste // uint32_t functionOffset; 540278332Semaste // compact_unwind_encoding_t encoding; 541278332Semaste 542278332Semaste uint16_t entry_page_offset = m_unwindinfo_data.GetU16(&offset); // entryPageOffset 543278332Semaste uint16_t entry_count = m_unwindinfo_data.GetU16(&offset); // entryCount 544278332Semaste 545278332Semaste 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); 546278332Semaste if (entry_offset == LLDB_INVALID_OFFSET) 547278332Semaste { 548278332Semaste return false; 549278332Semaste } 550278332Semaste entry_offset += 4; // skip over functionOffset 551278332Semaste unwind_info.encoding = m_unwindinfo_data.GetU32(&entry_offset); // encoding 552278332Semaste if (unwind_info.encoding & UNWIND_HAS_LSDA) 553278332Semaste { 554278332Semaste SectionList *sl = m_objfile.GetSectionList (); 555278332Semaste if (sl) 556278332Semaste { 557278332Semaste uint32_t lsda_offset = GetLSDAForFunctionOffset (lsda_array_start, lsda_array_count, function_offset); 558278332Semaste addr_t objfile_header_file_address = m_objfile.GetHeaderAddress().GetFileAddress(); 559278332Semaste unwind_info.lsda_address.ResolveAddressUsingFileSections (objfile_header_file_address + lsda_offset, sl); 560278332Semaste } 561278332Semaste } 562278332Semaste if (unwind_info.encoding & UNWIND_PERSONALITY_MASK) 563278332Semaste { 564278332Semaste uint32_t personality_index = EXTRACT_BITS (unwind_info.encoding, UNWIND_PERSONALITY_MASK); 565278332Semaste 566278332Semaste if (personality_index > 0) 567278332Semaste { 568278332Semaste personality_index--; 569278332Semaste if (personality_index < m_unwind_header.personality_array_count) 570278332Semaste { 571278332Semaste offset_t offset = m_unwind_header.personality_array_offset; 572278332Semaste offset += 4 * personality_index; 573278332Semaste SectionList *sl = m_objfile.GetSectionList (); 574278332Semaste if (sl) 575278332Semaste { 576278332Semaste uint32_t personality_offset = m_unwindinfo_data.GetU32(&offset); 577278332Semaste addr_t objfile_header_file_address = m_objfile.GetHeaderAddress().GetFileAddress(); 578278332Semaste unwind_info.personality_ptr_address.ResolveAddressUsingFileSections (objfile_header_file_address + personality_offset, sl); 579278332Semaste } 580278332Semaste } 581278332Semaste } 582278332Semaste } 583278332Semaste return true; 584278332Semaste } 585278332Semaste else if (kind == UNWIND_SECOND_LEVEL_COMPRESSED) 586278332Semaste { 587278332Semaste // struct unwind_info_compressed_second_level_page_header 588278332Semaste // { 589278332Semaste // uint32_t kind; // UNWIND_SECOND_LEVEL_COMPRESSED 590278332Semaste // uint16_t entryPageOffset; // offset from this 2nd lvl page idx to array of entries 591278332Semaste // // (an entry has a function offset and index into the encodings) 592278332Semaste // // NB function offset from the entry in the compressed page 593278332Semaste // // must be added to the index's functionOffset value. 594278332Semaste // uint16_t entryCount; 595278332Semaste // uint16_t encodingsPageOffset; // offset from this 2nd lvl page idx to array of encodings 596278332Semaste // uint16_t encodingsCount; 597278332Semaste 598278332Semaste uint16_t entry_page_offset = m_unwindinfo_data.GetU16(&offset); // entryPageOffset 599278332Semaste uint16_t entry_count = m_unwindinfo_data.GetU16(&offset); // entryCount 600278332Semaste uint16_t encodings_page_offset = m_unwindinfo_data.GetU16(&offset); // encodingsPageOffset 601278332Semaste uint16_t encodings_count = m_unwindinfo_data.GetU16(&offset); // encodingsCount 602278332Semaste 603278332Semaste 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); 604278332Semaste if (encoding_index == UINT32_MAX || encoding_index >= encodings_count + m_unwind_header.common_encodings_array_count) 605278332Semaste { 606278332Semaste return false; 607278332Semaste } 608278332Semaste uint32_t encoding = 0; 609278332Semaste if (encoding_index < m_unwind_header.common_encodings_array_count) 610278332Semaste { 611278332Semaste offset = m_unwind_header.common_encodings_array_offset + (encoding_index * sizeof (uint32_t)); 612278332Semaste encoding = m_unwindinfo_data.GetU32(&offset); // encoding entry from the commonEncodingsArray 613278332Semaste } 614278332Semaste else 615278332Semaste { 616278332Semaste uint32_t page_specific_entry_index = encoding_index - m_unwind_header.common_encodings_array_count; 617278332Semaste offset = second_page_offset + encodings_page_offset + (page_specific_entry_index * sizeof (uint32_t)); 618278332Semaste encoding = m_unwindinfo_data.GetU32(&offset); // encoding entry from the page-specific encoding array 619278332Semaste } 620278332Semaste if (encoding == 0) 621278332Semaste return false; 622278332Semaste 623278332Semaste unwind_info.encoding = encoding; 624278332Semaste if (unwind_info.encoding & UNWIND_HAS_LSDA) 625278332Semaste { 626278332Semaste SectionList *sl = m_objfile.GetSectionList (); 627278332Semaste if (sl) 628278332Semaste { 629278332Semaste uint32_t lsda_offset = GetLSDAForFunctionOffset (lsda_array_start, lsda_array_count, function_offset); 630278332Semaste addr_t objfile_header_file_address = m_objfile.GetHeaderAddress().GetFileAddress(); 631278332Semaste unwind_info.lsda_address.ResolveAddressUsingFileSections (objfile_header_file_address + lsda_offset, sl); 632278332Semaste } 633278332Semaste } 634278332Semaste if (unwind_info.encoding & UNWIND_PERSONALITY_MASK) 635278332Semaste { 636278332Semaste uint32_t personality_index = EXTRACT_BITS (unwind_info.encoding, UNWIND_PERSONALITY_MASK); 637278332Semaste 638278332Semaste if (personality_index > 0) 639278332Semaste { 640278332Semaste personality_index--; 641278332Semaste if (personality_index < m_unwind_header.personality_array_count) 642278332Semaste { 643278332Semaste offset_t offset = m_unwind_header.personality_array_offset; 644278332Semaste offset += 4 * personality_index; 645278332Semaste SectionList *sl = m_objfile.GetSectionList (); 646278332Semaste if (sl) 647278332Semaste { 648278332Semaste uint32_t personality_offset = m_unwindinfo_data.GetU32(&offset); 649278332Semaste addr_t objfile_header_file_address = m_objfile.GetHeaderAddress().GetFileAddress(); 650278332Semaste unwind_info.personality_ptr_address.ResolveAddressUsingFileSections (objfile_header_file_address + personality_offset, sl); 651278332Semaste } 652278332Semaste } 653278332Semaste } 654278332Semaste } 655278332Semaste return true; 656278332Semaste } 657278332Semaste return false; 658278332Semaste} 659278332Semaste 660278332Semasteenum x86_64_eh_regnum { 661278332Semaste rax = 0, 662278332Semaste rdx = 1, 663278332Semaste rcx = 2, 664278332Semaste rbx = 3, 665278332Semaste rsi = 4, 666278332Semaste rdi = 5, 667278332Semaste rbp = 6, 668278332Semaste rsp = 7, 669278332Semaste r8 = 8, 670278332Semaste r9 = 9, 671278332Semaste r10 = 10, 672278332Semaste r11 = 11, 673278332Semaste r12 = 12, 674278332Semaste r13 = 13, 675278332Semaste r14 = 14, 676278332Semaste r15 = 15, 677278332Semaste rip = 16 // this is officially the Return Address register number, but close enough 678278332Semaste}; 679278332Semaste 680278332Semaste// Convert the compact_unwind_info.h register numbering scheme 681278332Semaste// to eRegisterKindGCC (eh_frame) register numbering scheme. 682278332Semasteuint32_t 683278332Semastetranslate_to_eh_frame_regnum_x86_64 (uint32_t unwind_regno) 684278332Semaste{ 685278332Semaste switch (unwind_regno) 686278332Semaste { 687278332Semaste case UNWIND_X86_64_REG_RBX: 688278332Semaste return x86_64_eh_regnum::rbx; 689278332Semaste case UNWIND_X86_64_REG_R12: 690278332Semaste return x86_64_eh_regnum::r12; 691278332Semaste case UNWIND_X86_64_REG_R13: 692278332Semaste return x86_64_eh_regnum::r13; 693278332Semaste case UNWIND_X86_64_REG_R14: 694278332Semaste return x86_64_eh_regnum::r14; 695278332Semaste case UNWIND_X86_64_REG_R15: 696278332Semaste return x86_64_eh_regnum::r15; 697278332Semaste case UNWIND_X86_64_REG_RBP: 698278332Semaste return x86_64_eh_regnum::rbp; 699278332Semaste default: 700278332Semaste return LLDB_INVALID_REGNUM; 701278332Semaste } 702278332Semaste} 703278332Semaste 704278332Semastebool 705278332SemasteCompactUnwindInfo::CreateUnwindPlan_x86_64 (Target &target, FunctionInfo &function_info, UnwindPlan &unwind_plan, Address pc_or_function_start) 706278332Semaste{ 707278332Semaste unwind_plan.SetSourceName ("compact unwind info"); 708278332Semaste unwind_plan.SetSourcedFromCompiler (eLazyBoolYes); 709278332Semaste unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo); 710278332Semaste unwind_plan.SetRegisterKind (eRegisterKindGCC); 711278332Semaste 712278332Semaste unwind_plan.SetLSDAAddress (function_info.lsda_address); 713278332Semaste unwind_plan.SetPersonalityFunctionPtr (function_info.personality_ptr_address); 714278332Semaste 715278332Semaste UnwindPlan::RowSP row (new UnwindPlan::Row); 716278332Semaste 717278332Semaste const int wordsize = 8; 718278332Semaste int mode = function_info.encoding & UNWIND_X86_64_MODE_MASK; 719278332Semaste switch (mode) 720278332Semaste { 721278332Semaste case UNWIND_X86_64_MODE_RBP_FRAME: 722278332Semaste { 723278332Semaste row->SetCFARegister (translate_to_eh_frame_regnum_x86_64 (UNWIND_X86_64_REG_RBP)); 724278332Semaste row->SetCFAOffset (2 * wordsize); 725278332Semaste row->SetOffset (0); 726278332Semaste row->SetRegisterLocationToAtCFAPlusOffset (x86_64_eh_regnum::rbp, wordsize * -2, true); 727278332Semaste row->SetRegisterLocationToAtCFAPlusOffset (x86_64_eh_regnum::rip, wordsize * -1, true); 728278332Semaste row->SetRegisterLocationToIsCFAPlusOffset (x86_64_eh_regnum::rsp, 0, true); 729278332Semaste 730278332Semaste uint32_t saved_registers_offset = EXTRACT_BITS (function_info.encoding, UNWIND_X86_64_RBP_FRAME_OFFSET); 731278332Semaste 732278332Semaste uint32_t saved_registers_locations = EXTRACT_BITS (function_info.encoding, UNWIND_X86_64_RBP_FRAME_REGISTERS); 733278332Semaste 734278332Semaste saved_registers_offset += 2; 735278332Semaste 736278332Semaste for (int i = 0; i < 5; i++) 737278332Semaste { 738278332Semaste uint32_t regnum = saved_registers_locations & 0x7; 739278332Semaste switch (regnum) 740278332Semaste { 741278332Semaste case UNWIND_X86_64_REG_NONE: 742278332Semaste break; 743278332Semaste case UNWIND_X86_64_REG_RBX: 744278332Semaste case UNWIND_X86_64_REG_R12: 745278332Semaste case UNWIND_X86_64_REG_R13: 746278332Semaste case UNWIND_X86_64_REG_R14: 747278332Semaste case UNWIND_X86_64_REG_R15: 748278332Semaste row->SetRegisterLocationToAtCFAPlusOffset (translate_to_eh_frame_regnum_x86_64 (regnum), wordsize * -saved_registers_offset, true); 749278332Semaste break; 750278332Semaste } 751278332Semaste saved_registers_offset--; 752278332Semaste saved_registers_locations >>= 3; 753278332Semaste } 754278332Semaste unwind_plan.AppendRow (row); 755278332Semaste return true; 756278332Semaste } 757278332Semaste break; 758278332Semaste 759278332Semaste case UNWIND_X86_64_MODE_STACK_IND: 760278332Semaste { 761278332Semaste // The clang in Xcode 6 is emitting incorrect compact unwind encodings for this 762278332Semaste // style of unwind. It was fixed in llvm r217020. 763278332Semaste return false; 764278332Semaste } 765278332Semaste break; 766278332Semaste 767278332Semaste case UNWIND_X86_64_MODE_STACK_IMMD: 768278332Semaste { 769278332Semaste uint32_t stack_size = EXTRACT_BITS (function_info.encoding, UNWIND_X86_64_FRAMELESS_STACK_SIZE); 770278332Semaste uint32_t register_count = EXTRACT_BITS (function_info.encoding, UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT); 771278332Semaste uint32_t permutation = EXTRACT_BITS (function_info.encoding, UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION); 772278332Semaste 773278332Semaste if (mode == UNWIND_X86_64_MODE_STACK_IND && function_info.valid_range_offset_start != 0) 774278332Semaste { 775278332Semaste uint32_t stack_adjust = EXTRACT_BITS (function_info.encoding, UNWIND_X86_64_FRAMELESS_STACK_ADJUST); 776278332Semaste 777278332Semaste // offset into the function instructions; 0 == beginning of first instruction 778278332Semaste uint32_t offset_to_subl_insn = EXTRACT_BITS (function_info.encoding, UNWIND_X86_64_FRAMELESS_STACK_SIZE); 779278332Semaste 780278332Semaste SectionList *sl = m_objfile.GetSectionList (); 781278332Semaste if (sl) 782278332Semaste { 783278332Semaste ProcessSP process_sp = target.GetProcessSP(); 784278332Semaste if (process_sp) 785278332Semaste { 786278332Semaste Address subl_payload_addr (function_info.valid_range_offset_start, sl); 787278332Semaste subl_payload_addr.Slide (offset_to_subl_insn); 788278332Semaste Error error; 789278332Semaste uint64_t large_stack_size = process_sp->ReadUnsignedIntegerFromMemory (subl_payload_addr.GetLoadAddress (&target), 790278332Semaste 4, 0, error); 791278332Semaste if (large_stack_size != 0 && error.Success ()) 792278332Semaste { 793278332Semaste // Got the large stack frame size correctly - use it 794278332Semaste stack_size = large_stack_size + (stack_adjust * wordsize); 795278332Semaste } 796278332Semaste else 797278332Semaste { 798278332Semaste return false; 799278332Semaste } 800278332Semaste } 801278332Semaste else 802278332Semaste { 803278332Semaste return false; 804278332Semaste } 805278332Semaste } 806278332Semaste else 807278332Semaste { 808278332Semaste return false; 809278332Semaste } 810278332Semaste } 811278332Semaste 812278332Semaste row->SetCFARegister (x86_64_eh_regnum::rsp); 813278332Semaste row->SetCFAOffset (stack_size * wordsize); 814278332Semaste row->SetOffset (0); 815278332Semaste row->SetRegisterLocationToAtCFAPlusOffset (x86_64_eh_regnum::rip, wordsize * -1, true); 816278332Semaste row->SetRegisterLocationToIsCFAPlusOffset (x86_64_eh_regnum::rsp, 0, true); 817278332Semaste 818278332Semaste if (register_count > 0) 819278332Semaste { 820278332Semaste 821278332Semaste // We need to include (up to) 6 registers in 10 bits. 822278332Semaste // That would be 18 bits if we just used 3 bits per reg to indicate 823278332Semaste // the order they're saved on the stack. 824278332Semaste // 825278332Semaste // This is done with Lehmer code permutation, e.g. see 826278332Semaste // http://stackoverflow.com/questions/1506078/fast-permutation-number-permutation-mapping-algorithms 827278332Semaste int permunreg[6]; 828278332Semaste 829278332Semaste // This decodes the variable-base number in the 10 bits 830278332Semaste // and gives us the Lehmer code sequence which can then 831278332Semaste // be decoded. 832278332Semaste 833278332Semaste switch (register_count) 834278332Semaste { 835278332Semaste case 6: 836278332Semaste permunreg[0] = permutation/120; // 120 == 5! 837278332Semaste permutation -= (permunreg[0]*120); 838278332Semaste permunreg[1] = permutation/24; // 24 == 4! 839278332Semaste permutation -= (permunreg[1]*24); 840278332Semaste permunreg[2] = permutation/6; // 6 == 3! 841278332Semaste permutation -= (permunreg[2]*6); 842278332Semaste permunreg[3] = permutation/2; // 2 == 2! 843278332Semaste permutation -= (permunreg[3]*2); 844278332Semaste permunreg[4] = permutation; // 1 == 1! 845278332Semaste permunreg[5] = 0; 846278332Semaste break; 847278332Semaste case 5: 848278332Semaste permunreg[0] = permutation/120; 849278332Semaste permutation -= (permunreg[0]*120); 850278332Semaste permunreg[1] = permutation/24; 851278332Semaste permutation -= (permunreg[1]*24); 852278332Semaste permunreg[2] = permutation/6; 853278332Semaste permutation -= (permunreg[2]*6); 854278332Semaste permunreg[3] = permutation/2; 855278332Semaste permutation -= (permunreg[3]*2); 856278332Semaste permunreg[4] = permutation; 857278332Semaste break; 858278332Semaste case 4: 859278332Semaste permunreg[0] = permutation/60; 860278332Semaste permutation -= (permunreg[0]*60); 861278332Semaste permunreg[1] = permutation/12; 862278332Semaste permutation -= (permunreg[1]*12); 863278332Semaste permunreg[2] = permutation/3; 864278332Semaste permutation -= (permunreg[2]*3); 865278332Semaste permunreg[3] = permutation; 866278332Semaste break; 867278332Semaste case 3: 868278332Semaste permunreg[0] = permutation/20; 869278332Semaste permutation -= (permunreg[0]*20); 870278332Semaste permunreg[1] = permutation/4; 871278332Semaste permutation -= (permunreg[1]*4); 872278332Semaste permunreg[2] = permutation; 873278332Semaste break; 874278332Semaste case 2: 875278332Semaste permunreg[0] = permutation/5; 876278332Semaste permutation -= (permunreg[0]*5); 877278332Semaste permunreg[1] = permutation; 878278332Semaste break; 879278332Semaste case 1: 880278332Semaste permunreg[0] = permutation; 881278332Semaste break; 882278332Semaste } 883278332Semaste 884278332Semaste // Decode the Lehmer code for this permutation of 885278332Semaste // the registers v. http://en.wikipedia.org/wiki/Lehmer_code 886278332Semaste 887278332Semaste int registers[6]; 888278332Semaste bool used[7] = { false, false, false, false, false, false, false }; 889278332Semaste for (uint32_t i = 0; i < register_count; i++) 890278332Semaste { 891278332Semaste int renum = 0; 892278332Semaste for (int j = 1; j < 7; j++) 893278332Semaste { 894278332Semaste if (used[j] == false) 895278332Semaste { 896278332Semaste if (renum == permunreg[i]) 897278332Semaste { 898278332Semaste registers[i] = j; 899278332Semaste used[j] = true; 900278332Semaste break; 901278332Semaste } 902278332Semaste renum++; 903278332Semaste } 904278332Semaste } 905278332Semaste } 906278332Semaste 907278332Semaste uint32_t saved_registers_offset = 1; 908278332Semaste saved_registers_offset++; 909278332Semaste 910278332Semaste for (int i = (sizeof (registers) / sizeof (int)) - 1; i >= 0; i--) 911278332Semaste { 912278332Semaste switch (registers[i]) 913278332Semaste { 914278332Semaste case UNWIND_X86_64_REG_NONE: 915278332Semaste break; 916278332Semaste case UNWIND_X86_64_REG_RBX: 917278332Semaste case UNWIND_X86_64_REG_R12: 918278332Semaste case UNWIND_X86_64_REG_R13: 919278332Semaste case UNWIND_X86_64_REG_R14: 920278332Semaste case UNWIND_X86_64_REG_R15: 921278332Semaste case UNWIND_X86_64_REG_RBP: 922278332Semaste row->SetRegisterLocationToAtCFAPlusOffset (translate_to_eh_frame_regnum_x86_64 (registers[i]), wordsize * -saved_registers_offset, true); 923278332Semaste break; 924278332Semaste } 925278332Semaste saved_registers_offset++; 926278332Semaste } 927278332Semaste } 928278332Semaste unwind_plan.AppendRow (row); 929278332Semaste return true; 930278332Semaste } 931278332Semaste break; 932278332Semaste 933278332Semaste case UNWIND_X86_64_MODE_DWARF: 934278332Semaste { 935278332Semaste return false; 936278332Semaste } 937278332Semaste break; 938278332Semaste 939278332Semaste case 0: 940278332Semaste { 941278332Semaste return false; 942278332Semaste } 943278332Semaste break; 944278332Semaste } 945278332Semaste return false; 946278332Semaste} 947278332Semaste 948278332Semasteenum i386_eh_regnum { 949278332Semaste eax = 0, 950278332Semaste ecx = 1, 951278332Semaste edx = 2, 952278332Semaste ebx = 3, 953278332Semaste ebp = 4, 954278332Semaste esp = 5, 955278332Semaste esi = 6, 956278332Semaste edi = 7, 957278332Semaste eip = 8 // this is officially the Return Address register number, but close enough 958278332Semaste}; 959278332Semaste 960278332Semaste// Convert the compact_unwind_info.h register numbering scheme 961278332Semaste// to eRegisterKindGCC (eh_frame) register numbering scheme. 962278332Semasteuint32_t 963278332Semastetranslate_to_eh_frame_regnum_i386 (uint32_t unwind_regno) 964278332Semaste{ 965278332Semaste switch (unwind_regno) 966278332Semaste { 967278332Semaste case UNWIND_X86_REG_EBX: 968278332Semaste return i386_eh_regnum::ebx; 969278332Semaste case UNWIND_X86_REG_ECX: 970278332Semaste return i386_eh_regnum::ecx; 971278332Semaste case UNWIND_X86_REG_EDX: 972278332Semaste return i386_eh_regnum::edx; 973278332Semaste case UNWIND_X86_REG_EDI: 974278332Semaste return i386_eh_regnum::edi; 975278332Semaste case UNWIND_X86_REG_ESI: 976278332Semaste return i386_eh_regnum::esi; 977278332Semaste case UNWIND_X86_REG_EBP: 978278332Semaste return i386_eh_regnum::ebp; 979278332Semaste default: 980278332Semaste return LLDB_INVALID_REGNUM; 981278332Semaste } 982278332Semaste} 983278332Semaste 984278332Semaste 985278332Semastebool 986278332SemasteCompactUnwindInfo::CreateUnwindPlan_i386 (Target &target, FunctionInfo &function_info, UnwindPlan &unwind_plan, Address pc_or_function_start) 987278332Semaste{ 988278332Semaste unwind_plan.SetSourceName ("compact unwind info"); 989278332Semaste unwind_plan.SetSourcedFromCompiler (eLazyBoolYes); 990278332Semaste unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo); 991278332Semaste unwind_plan.SetRegisterKind (eRegisterKindGCC); 992278332Semaste 993278332Semaste unwind_plan.SetLSDAAddress (function_info.lsda_address); 994278332Semaste unwind_plan.SetPersonalityFunctionPtr (function_info.personality_ptr_address); 995278332Semaste 996278332Semaste UnwindPlan::RowSP row (new UnwindPlan::Row); 997278332Semaste 998278332Semaste const int wordsize = 4; 999278332Semaste int mode = function_info.encoding & UNWIND_X86_MODE_MASK; 1000278332Semaste switch (mode) 1001278332Semaste { 1002278332Semaste case UNWIND_X86_MODE_EBP_FRAME: 1003278332Semaste { 1004278332Semaste row->SetCFARegister (translate_to_eh_frame_regnum_i386 (UNWIND_X86_REG_EBP)); 1005278332Semaste row->SetCFAOffset (2 * wordsize); 1006278332Semaste row->SetOffset (0); 1007278332Semaste row->SetRegisterLocationToAtCFAPlusOffset (i386_eh_regnum::ebp, wordsize * -2, true); 1008278332Semaste row->SetRegisterLocationToAtCFAPlusOffset (i386_eh_regnum::eip, wordsize * -1, true); 1009278332Semaste row->SetRegisterLocationToIsCFAPlusOffset (i386_eh_regnum::esp, 0, true); 1010278332Semaste 1011278332Semaste uint32_t saved_registers_offset = EXTRACT_BITS (function_info.encoding, UNWIND_X86_EBP_FRAME_OFFSET); 1012278332Semaste 1013278332Semaste uint32_t saved_registers_locations = EXTRACT_BITS (function_info.encoding, UNWIND_X86_EBP_FRAME_REGISTERS); 1014278332Semaste 1015278332Semaste saved_registers_offset += 2; 1016278332Semaste 1017278332Semaste for (int i = 0; i < 5; i++) 1018278332Semaste { 1019278332Semaste uint32_t regnum = saved_registers_locations & 0x7; 1020278332Semaste switch (regnum) 1021278332Semaste { 1022278332Semaste case UNWIND_X86_REG_NONE: 1023278332Semaste break; 1024278332Semaste case UNWIND_X86_REG_EBX: 1025278332Semaste case UNWIND_X86_REG_ECX: 1026278332Semaste case UNWIND_X86_REG_EDX: 1027278332Semaste case UNWIND_X86_REG_EDI: 1028278332Semaste case UNWIND_X86_REG_ESI: 1029278332Semaste row->SetRegisterLocationToAtCFAPlusOffset (translate_to_eh_frame_regnum_i386 (regnum), wordsize * -saved_registers_offset, true); 1030278332Semaste break; 1031278332Semaste } 1032278332Semaste saved_registers_offset--; 1033278332Semaste saved_registers_locations >>= 3; 1034278332Semaste } 1035278332Semaste unwind_plan.AppendRow (row); 1036278332Semaste return true; 1037278332Semaste } 1038278332Semaste break; 1039278332Semaste 1040278332Semaste case UNWIND_X86_MODE_STACK_IND: 1041278332Semaste case UNWIND_X86_MODE_STACK_IMMD: 1042278332Semaste { 1043278332Semaste uint32_t stack_size = EXTRACT_BITS (function_info.encoding, UNWIND_X86_FRAMELESS_STACK_SIZE); 1044278332Semaste uint32_t register_count = EXTRACT_BITS (function_info.encoding, UNWIND_X86_FRAMELESS_STACK_REG_COUNT); 1045278332Semaste uint32_t permutation = EXTRACT_BITS (function_info.encoding, UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION); 1046278332Semaste 1047278332Semaste if (mode == UNWIND_X86_MODE_STACK_IND && function_info.valid_range_offset_start != 0) 1048278332Semaste { 1049278332Semaste uint32_t stack_adjust = EXTRACT_BITS (function_info.encoding, UNWIND_X86_FRAMELESS_STACK_ADJUST); 1050278332Semaste 1051278332Semaste // offset into the function instructions; 0 == beginning of first instruction 1052278332Semaste uint32_t offset_to_subl_insn = EXTRACT_BITS (function_info.encoding, UNWIND_X86_FRAMELESS_STACK_SIZE); 1053278332Semaste 1054278332Semaste SectionList *sl = m_objfile.GetSectionList (); 1055278332Semaste if (sl) 1056278332Semaste { 1057278332Semaste ProcessSP process_sp = target.GetProcessSP(); 1058278332Semaste if (process_sp) 1059278332Semaste { 1060278332Semaste Address subl_payload_addr (function_info.valid_range_offset_start, sl); 1061278332Semaste subl_payload_addr.Slide (offset_to_subl_insn); 1062278332Semaste Error error; 1063278332Semaste uint64_t large_stack_size = process_sp->ReadUnsignedIntegerFromMemory (subl_payload_addr.GetLoadAddress (&target), 1064278332Semaste 4, 0, error); 1065278332Semaste if (large_stack_size != 0 && error.Success ()) 1066278332Semaste { 1067278332Semaste // Got the large stack frame size correctly - use it 1068278332Semaste stack_size = large_stack_size + (stack_adjust * wordsize); 1069278332Semaste } 1070278332Semaste else 1071278332Semaste { 1072278332Semaste return false; 1073278332Semaste } 1074278332Semaste } 1075278332Semaste else 1076278332Semaste { 1077278332Semaste return false; 1078278332Semaste } 1079278332Semaste } 1080278332Semaste else 1081278332Semaste { 1082278332Semaste return false; 1083278332Semaste } 1084278332Semaste } 1085278332Semaste 1086278332Semaste row->SetCFARegister (i386_eh_regnum::esp); 1087278332Semaste row->SetCFAOffset (stack_size * wordsize); 1088278332Semaste row->SetOffset (0); 1089278332Semaste row->SetRegisterLocationToAtCFAPlusOffset (i386_eh_regnum::eip, wordsize * -1, true); 1090278332Semaste row->SetRegisterLocationToIsCFAPlusOffset (i386_eh_regnum::esp, 0, true); 1091278332Semaste 1092278332Semaste if (register_count > 0) 1093278332Semaste { 1094278332Semaste 1095278332Semaste // We need to include (up to) 6 registers in 10 bits. 1096278332Semaste // That would be 18 bits if we just used 3 bits per reg to indicate 1097278332Semaste // the order they're saved on the stack. 1098278332Semaste // 1099278332Semaste // This is done with Lehmer code permutation, e.g. see 1100278332Semaste // http://stackoverflow.com/questions/1506078/fast-permutation-number-permutation-mapping-algorithms 1101278332Semaste int permunreg[6]; 1102278332Semaste 1103278332Semaste // This decodes the variable-base number in the 10 bits 1104278332Semaste // and gives us the Lehmer code sequence which can then 1105278332Semaste // be decoded. 1106278332Semaste 1107278332Semaste switch (register_count) 1108278332Semaste { 1109278332Semaste case 6: 1110278332Semaste permunreg[0] = permutation/120; // 120 == 5! 1111278332Semaste permutation -= (permunreg[0]*120); 1112278332Semaste permunreg[1] = permutation/24; // 24 == 4! 1113278332Semaste permutation -= (permunreg[1]*24); 1114278332Semaste permunreg[2] = permutation/6; // 6 == 3! 1115278332Semaste permutation -= (permunreg[2]*6); 1116278332Semaste permunreg[3] = permutation/2; // 2 == 2! 1117278332Semaste permutation -= (permunreg[3]*2); 1118278332Semaste permunreg[4] = permutation; // 1 == 1! 1119278332Semaste permunreg[5] = 0; 1120278332Semaste break; 1121278332Semaste case 5: 1122278332Semaste permunreg[0] = permutation/120; 1123278332Semaste permutation -= (permunreg[0]*120); 1124278332Semaste permunreg[1] = permutation/24; 1125278332Semaste permutation -= (permunreg[1]*24); 1126278332Semaste permunreg[2] = permutation/6; 1127278332Semaste permutation -= (permunreg[2]*6); 1128278332Semaste permunreg[3] = permutation/2; 1129278332Semaste permutation -= (permunreg[3]*2); 1130278332Semaste permunreg[4] = permutation; 1131278332Semaste break; 1132278332Semaste case 4: 1133278332Semaste permunreg[0] = permutation/60; 1134278332Semaste permutation -= (permunreg[0]*60); 1135278332Semaste permunreg[1] = permutation/12; 1136278332Semaste permutation -= (permunreg[1]*12); 1137278332Semaste permunreg[2] = permutation/3; 1138278332Semaste permutation -= (permunreg[2]*3); 1139278332Semaste permunreg[3] = permutation; 1140278332Semaste break; 1141278332Semaste case 3: 1142278332Semaste permunreg[0] = permutation/20; 1143278332Semaste permutation -= (permunreg[0]*20); 1144278332Semaste permunreg[1] = permutation/4; 1145278332Semaste permutation -= (permunreg[1]*4); 1146278332Semaste permunreg[2] = permutation; 1147278332Semaste break; 1148278332Semaste case 2: 1149278332Semaste permunreg[0] = permutation/5; 1150278332Semaste permutation -= (permunreg[0]*5); 1151278332Semaste permunreg[1] = permutation; 1152278332Semaste break; 1153278332Semaste case 1: 1154278332Semaste permunreg[0] = permutation; 1155278332Semaste break; 1156278332Semaste } 1157278332Semaste 1158278332Semaste // Decode the Lehmer code for this permutation of 1159278332Semaste // the registers v. http://en.wikipedia.org/wiki/Lehmer_code 1160278332Semaste 1161278332Semaste int registers[6]; 1162278332Semaste bool used[7] = { false, false, false, false, false, false, false }; 1163278332Semaste for (uint32_t i = 0; i < register_count; i++) 1164278332Semaste { 1165278332Semaste int renum = 0; 1166278332Semaste for (int j = 1; j < 7; j++) 1167278332Semaste { 1168278332Semaste if (used[j] == false) 1169278332Semaste { 1170278332Semaste if (renum == permunreg[i]) 1171278332Semaste { 1172278332Semaste registers[i] = j; 1173278332Semaste used[j] = true; 1174278332Semaste break; 1175278332Semaste } 1176278332Semaste renum++; 1177278332Semaste } 1178278332Semaste } 1179278332Semaste } 1180278332Semaste 1181278332Semaste uint32_t saved_registers_offset = 1; 1182278332Semaste saved_registers_offset++; 1183278332Semaste 1184278332Semaste for (int i = (sizeof (registers) / sizeof (int)) - 1; i >= 0; i--) 1185278332Semaste { 1186278332Semaste switch (registers[i]) 1187278332Semaste { 1188278332Semaste case UNWIND_X86_REG_NONE: 1189278332Semaste break; 1190278332Semaste case UNWIND_X86_REG_EBX: 1191278332Semaste case UNWIND_X86_REG_ECX: 1192278332Semaste case UNWIND_X86_REG_EDX: 1193278332Semaste case UNWIND_X86_REG_EDI: 1194278332Semaste case UNWIND_X86_REG_ESI: 1195278332Semaste case UNWIND_X86_REG_EBP: 1196278332Semaste row->SetRegisterLocationToAtCFAPlusOffset (translate_to_eh_frame_regnum_i386 (registers[i]), wordsize * -saved_registers_offset, true); 1197278332Semaste break; 1198278332Semaste } 1199278332Semaste saved_registers_offset++; 1200278332Semaste } 1201278332Semaste } 1202278332Semaste 1203278332Semaste unwind_plan.AppendRow (row); 1204278332Semaste return true; 1205278332Semaste } 1206278332Semaste break; 1207278332Semaste 1208278332Semaste case UNWIND_X86_MODE_DWARF: 1209278332Semaste { 1210278332Semaste return false; 1211278332Semaste } 1212278332Semaste break; 1213278332Semaste } 1214278332Semaste return false; 1215278332Semaste} 1216