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