[lldb][NFC] Fix all formatting errors in .cpp file headers
Summary:
A *.cpp file header in LLDB (and in LLDB) should like this:
```
//===-- TestUtilities.cpp -------------------------------------------------===//
```
However in LLDB most of our source files have arbitrary changes to this format and
these changes are spreading through LLDB as folks usually just use the existing
source files as templates for their new files (most notably the unnecessary
editor language indicator `-*- C++ -*-` is spreading and in every review
someone is pointing out that this is wrong, resulting in people pointing out that this
is done in the same way in other files).
This patch removes most of these inconsistencies including the editor language indicators,
all the different missing/additional '-' characters, files that center the file name, missing
trailing `===//` (mostly caused by clang-format breaking the line).
Reviewers: aprantl, espindola, jfb, shafik, JDevlieghere
Reviewed By: JDevlieghere
Subscribers: dexonsmith, wuzish, emaste, sdardis, nemanjai, kbarton, MaskRay, atanasyan, arphaman, jfb, abidh, jsji, JDevlieghere, usaxena95, lldb-commits
Tags: #lldb
Differential Revision: https://reviews.llvm.org/D73258
2020-01-24 15:23:27 +08:00
|
|
|
//===-- CompactUnwindInfo.cpp ---------------------------------------------===//
|
2014-12-08 11:09:00 +08:00
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2014-12-08 11:09:00 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2017-11-14 00:16:33 +08:00
|
|
|
#include "lldb/Symbol/CompactUnwindInfo.h"
|
2014-12-08 11:09:00 +08:00
|
|
|
#include "lldb/Core/Module.h"
|
|
|
|
#include "lldb/Core/Section.h"
|
|
|
|
#include "lldb/Symbol/ObjectFile.h"
|
|
|
|
#include "lldb/Symbol/UnwindPlan.h"
|
2014-12-20 11:12:51 +08:00
|
|
|
#include "lldb/Target/Process.h"
|
|
|
|
#include "lldb/Target/Target.h"
|
2017-11-14 00:16:33 +08:00
|
|
|
#include "lldb/Utility/ArchSpec.h"
|
2017-03-04 09:30:05 +08:00
|
|
|
#include "lldb/Utility/DataBufferHeap.h"
|
2017-03-04 04:56:28 +08:00
|
|
|
#include "lldb/Utility/Log.h"
|
2017-02-03 05:39:50 +08:00
|
|
|
#include "lldb/Utility/StreamString.h"
|
2014-12-08 11:09:00 +08:00
|
|
|
|
2014-12-09 04:00:33 +08:00
|
|
|
#include "llvm/Support/MathExtras.h"
|
|
|
|
|
2019-02-12 07:13:08 +08:00
|
|
|
#include <algorithm>
|
|
|
|
#include <memory>
|
|
|
|
|
2014-12-08 11:09:00 +08:00
|
|
|
using namespace lldb;
|
|
|
|
using namespace lldb_private;
|
|
|
|
|
|
|
|
namespace lldb_private {
|
|
|
|
|
|
|
|
// Constants from <mach-o/compact_unwind_encoding.h>
|
2016-06-07 10:19:54 +08:00
|
|
|
|
2015-04-03 04:57:38 +08:00
|
|
|
FLAGS_ANONYMOUS_ENUM(){
|
2014-12-08 11:09:00 +08:00
|
|
|
UNWIND_IS_NOT_FUNCTION_START = 0x80000000, UNWIND_HAS_LSDA = 0x40000000,
|
|
|
|
UNWIND_PERSONALITY_MASK = 0x30000000,
|
2015-05-13 08:25:54 +08:00
|
|
|
};
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2015-04-03 04:57:38 +08:00
|
|
|
FLAGS_ANONYMOUS_ENUM(){
|
2014-12-08 11:09:00 +08:00
|
|
|
UNWIND_X86_MODE_MASK = 0x0F000000,
|
|
|
|
UNWIND_X86_MODE_EBP_FRAME = 0x01000000,
|
|
|
|
UNWIND_X86_MODE_STACK_IMMD = 0x02000000,
|
|
|
|
UNWIND_X86_MODE_STACK_IND = 0x03000000,
|
|
|
|
UNWIND_X86_MODE_DWARF = 0x04000000,
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2014-12-08 11:09:00 +08:00
|
|
|
UNWIND_X86_EBP_FRAME_REGISTERS = 0x00007FFF,
|
|
|
|
UNWIND_X86_EBP_FRAME_OFFSET = 0x00FF0000,
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2014-12-08 11:09:00 +08:00
|
|
|
UNWIND_X86_FRAMELESS_STACK_SIZE = 0x00FF0000,
|
|
|
|
UNWIND_X86_FRAMELESS_STACK_ADJUST = 0x0000E000,
|
|
|
|
UNWIND_X86_FRAMELESS_STACK_REG_COUNT = 0x00001C00,
|
|
|
|
UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION = 0x000003FF,
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2014-12-08 11:09:00 +08:00
|
|
|
UNWIND_X86_DWARF_SECTION_OFFSET = 0x00FFFFFF,
|
2016-09-07 04:57:50 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
enum {
|
2014-12-08 11:09:00 +08:00
|
|
|
UNWIND_X86_REG_NONE = 0,
|
|
|
|
UNWIND_X86_REG_EBX = 1,
|
|
|
|
UNWIND_X86_REG_ECX = 2,
|
|
|
|
UNWIND_X86_REG_EDX = 3,
|
|
|
|
UNWIND_X86_REG_EDI = 4,
|
|
|
|
UNWIND_X86_REG_ESI = 5,
|
|
|
|
UNWIND_X86_REG_EBP = 6,
|
2016-09-07 04:57:50 +08:00
|
|
|
};
|
|
|
|
|
2015-04-03 04:57:38 +08:00
|
|
|
FLAGS_ANONYMOUS_ENUM(){
|
2014-12-08 11:09:00 +08:00
|
|
|
UNWIND_X86_64_MODE_MASK = 0x0F000000,
|
|
|
|
UNWIND_X86_64_MODE_RBP_FRAME = 0x01000000,
|
|
|
|
UNWIND_X86_64_MODE_STACK_IMMD = 0x02000000,
|
|
|
|
UNWIND_X86_64_MODE_STACK_IND = 0x03000000,
|
|
|
|
UNWIND_X86_64_MODE_DWARF = 0x04000000,
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2014-12-08 11:09:00 +08:00
|
|
|
UNWIND_X86_64_RBP_FRAME_REGISTERS = 0x00007FFF,
|
|
|
|
UNWIND_X86_64_RBP_FRAME_OFFSET = 0x00FF0000,
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2014-12-08 11:09:00 +08:00
|
|
|
UNWIND_X86_64_FRAMELESS_STACK_SIZE = 0x00FF0000,
|
|
|
|
UNWIND_X86_64_FRAMELESS_STACK_ADJUST = 0x0000E000,
|
|
|
|
UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT = 0x00001C00,
|
|
|
|
UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION = 0x000003FF,
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2014-12-08 11:09:00 +08:00
|
|
|
UNWIND_X86_64_DWARF_SECTION_OFFSET = 0x00FFFFFF,
|
2016-09-07 04:57:50 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
enum {
|
2014-12-08 11:09:00 +08:00
|
|
|
UNWIND_X86_64_REG_NONE = 0,
|
|
|
|
UNWIND_X86_64_REG_RBX = 1,
|
|
|
|
UNWIND_X86_64_REG_R12 = 2,
|
|
|
|
UNWIND_X86_64_REG_R13 = 3,
|
|
|
|
UNWIND_X86_64_REG_R14 = 4,
|
|
|
|
UNWIND_X86_64_REG_R15 = 5,
|
|
|
|
UNWIND_X86_64_REG_RBP = 6,
|
2016-09-07 04:57:50 +08:00
|
|
|
};
|
|
|
|
|
2016-05-25 12:20:28 +08:00
|
|
|
FLAGS_ANONYMOUS_ENUM(){
|
2016-06-07 10:19:54 +08:00
|
|
|
UNWIND_ARM64_MODE_MASK = 0x0F000000,
|
|
|
|
UNWIND_ARM64_MODE_FRAMELESS = 0x02000000,
|
|
|
|
UNWIND_ARM64_MODE_DWARF = 0x03000000,
|
|
|
|
UNWIND_ARM64_MODE_FRAME = 0x04000000,
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2016-06-07 10:19:54 +08:00
|
|
|
UNWIND_ARM64_FRAME_X19_X20_PAIR = 0x00000001,
|
|
|
|
UNWIND_ARM64_FRAME_X21_X22_PAIR = 0x00000002,
|
|
|
|
UNWIND_ARM64_FRAME_X23_X24_PAIR = 0x00000004,
|
|
|
|
UNWIND_ARM64_FRAME_X25_X26_PAIR = 0x00000008,
|
|
|
|
UNWIND_ARM64_FRAME_X27_X28_PAIR = 0x00000010,
|
|
|
|
UNWIND_ARM64_FRAME_D8_D9_PAIR = 0x00000100,
|
|
|
|
UNWIND_ARM64_FRAME_D10_D11_PAIR = 0x00000200,
|
|
|
|
UNWIND_ARM64_FRAME_D12_D13_PAIR = 0x00000400,
|
|
|
|
UNWIND_ARM64_FRAME_D14_D15_PAIR = 0x00000800,
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2016-06-07 10:19:54 +08:00
|
|
|
UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK = 0x00FFF000,
|
|
|
|
UNWIND_ARM64_DWARF_SECTION_OFFSET = 0x00FFFFFF,
|
2016-09-07 04:57:50 +08:00
|
|
|
};
|
|
|
|
|
2016-06-07 10:19:54 +08:00
|
|
|
FLAGS_ANONYMOUS_ENUM(){
|
|
|
|
UNWIND_ARM_MODE_MASK = 0x0F000000,
|
|
|
|
UNWIND_ARM_MODE_FRAME = 0x01000000,
|
|
|
|
UNWIND_ARM_MODE_FRAME_D = 0x02000000,
|
|
|
|
UNWIND_ARM_MODE_DWARF = 0x04000000,
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2016-06-07 10:19:54 +08:00
|
|
|
UNWIND_ARM_FRAME_STACK_ADJUST_MASK = 0x00C00000,
|
2014-12-08 11:09:00 +08:00
|
|
|
|
2016-06-07 10:19:54 +08:00
|
|
|
UNWIND_ARM_FRAME_FIRST_PUSH_R4 = 0x00000001,
|
|
|
|
UNWIND_ARM_FRAME_FIRST_PUSH_R5 = 0x00000002,
|
|
|
|
UNWIND_ARM_FRAME_FIRST_PUSH_R6 = 0x00000004,
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2016-06-07 10:19:54 +08:00
|
|
|
UNWIND_ARM_FRAME_SECOND_PUSH_R8 = 0x00000008,
|
|
|
|
UNWIND_ARM_FRAME_SECOND_PUSH_R9 = 0x00000010,
|
|
|
|
UNWIND_ARM_FRAME_SECOND_PUSH_R10 = 0x00000020,
|
|
|
|
UNWIND_ARM_FRAME_SECOND_PUSH_R11 = 0x00000040,
|
|
|
|
UNWIND_ARM_FRAME_SECOND_PUSH_R12 = 0x00000080,
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2016-06-07 10:19:54 +08:00
|
|
|
UNWIND_ARM_FRAME_D_REG_COUNT_MASK = 0x00000700,
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2016-06-07 10:19:54 +08:00
|
|
|
UNWIND_ARM_DWARF_SECTION_OFFSET = 0x00FFFFFF,
|
2016-09-07 04:57:50 +08:00
|
|
|
};
|
|
|
|
}
|
2014-12-08 11:09:00 +08:00
|
|
|
|
|
|
|
#ifndef UNWIND_SECOND_LEVEL_REGULAR
|
|
|
|
#define UNWIND_SECOND_LEVEL_REGULAR 2
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef UNWIND_SECOND_LEVEL_COMPRESSED
|
|
|
|
#define UNWIND_SECOND_LEVEL_COMPRESSED 3
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET
|
|
|
|
#define UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET(entry) (entry & 0x00FFFFFF)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX
|
|
|
|
#define UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX(entry) \
|
|
|
|
((entry >> 24) & 0xFF)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#define EXTRACT_BITS(value, mask) \
|
2014-12-09 04:00:33 +08:00
|
|
|
((value >> \
|
|
|
|
llvm::countTrailingZeros(static_cast<uint32_t>(mask), llvm::ZB_Width)) & \
|
2015-02-13 00:16:56 +08:00
|
|
|
(((1 << llvm::countPopulation(static_cast<uint32_t>(mask)))) - 1))
|
2014-12-08 11:09:00 +08:00
|
|
|
|
2016-06-07 10:19:54 +08:00
|
|
|
// constructor
|
2014-12-08 11:09:00 +08:00
|
|
|
|
2016-05-19 13:13:57 +08:00
|
|
|
CompactUnwindInfo::CompactUnwindInfo(ObjectFile &objfile, SectionSP §ion_sp)
|
|
|
|
: m_objfile(objfile), m_section_sp(section_sp),
|
|
|
|
m_section_contents_if_encrypted(), m_mutex(), m_indexes(),
|
|
|
|
m_indexes_computed(eLazyBoolCalculate), m_unwindinfo_data(),
|
|
|
|
m_unwindinfo_data_computed(false), m_unwind_header() {}
|
2014-12-08 11:09:00 +08:00
|
|
|
|
|
|
|
// destructor
|
|
|
|
|
|
|
|
CompactUnwindInfo::~CompactUnwindInfo() {}
|
2014-12-21 18:44:54 +08:00
|
|
|
|
2016-06-07 10:19:54 +08:00
|
|
|
bool CompactUnwindInfo::GetUnwindPlan(Target &target, Address addr,
|
2014-12-08 11:09:00 +08:00
|
|
|
UnwindPlan &unwind_plan) {
|
2016-06-07 10:19:54 +08:00
|
|
|
if (!IsValid(target.GetProcessSP())) {
|
|
|
|
return false;
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2016-06-07 10:19:54 +08:00
|
|
|
FunctionInfo function_info;
|
2014-12-21 18:44:54 +08:00
|
|
|
if (GetCompactUnwindInfoForFunction(target, addr, function_info)) {
|
|
|
|
// shortcut return for functions that have no compact unwind
|
|
|
|
if (function_info.encoding == 0)
|
|
|
|
return false;
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2019-01-03 18:37:19 +08:00
|
|
|
if (ArchSpec arch = m_objfile.GetArchitecture()) {
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2014-12-21 18:44:54 +08:00
|
|
|
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND));
|
|
|
|
if (log && log->GetVerbose()) {
|
|
|
|
StreamString strm;
|
|
|
|
addr.Dump(
|
[lldb] NFC modernize codebase with modernize-use-nullptr
Summary:
NFC = [[ https://llvm.org/docs/Lexicon.html#nfc | Non functional change ]]
This commit is the result of modernizing the LLDB codebase by using
`nullptr` instread of `0` or `NULL`. See
https://clang.llvm.org/extra/clang-tidy/checks/modernize-use-nullptr.html
for more information.
This is the command I ran and I to fix and format the code base:
```
run-clang-tidy.py \
-header-filter='.*' \
-checks='-*,modernize-use-nullptr' \
-fix ~/dev/llvm-project/lldb/.* \
-format \
-style LLVM \
-p ~/llvm-builds/debug-ninja-gcc
```
NOTE: There were also changes to `llvm/utils/unittest` but I did not
include them because I felt that maybe this library shall be updated in
isolation somehow.
NOTE: I know this is a rather large commit but it is a nobrainer in most
parts.
Reviewers: martong, espindola, shafik, #lldb, JDevlieghere
Reviewed By: JDevlieghere
Subscribers: arsenm, jvesely, nhaehnle, hiraditya, JDevlieghere, teemperor, rnkovacs, emaste, kubamracek, nemanjai, ki.stfu, javed.absar, arichardson, kbarton, jrtc27, MaskRay, atanasyan, dexonsmith, arphaman, jfb, jsji, jdoerfert, lldb-commits, llvm-commits
Tags: #lldb, #llvm
Differential Revision: https://reviews.llvm.org/D61847
llvm-svn: 361484
2019-05-23 19:14:47 +08:00
|
|
|
&strm, nullptr,
|
2014-12-21 18:44:54 +08:00
|
|
|
Address::DumpStyle::DumpStyleResolvedDescriptionNoFunctionArguments,
|
|
|
|
Address::DumpStyle::DumpStyleFileAddress,
|
|
|
|
arch.GetAddressByteSize());
|
2019-07-25 01:56:10 +08:00
|
|
|
LLDB_LOGF(log, "Got compact unwind encoding 0x%x for function %s",
|
|
|
|
function_info.encoding, strm.GetData());
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
|
2014-12-21 18:44:54 +08:00
|
|
|
if (function_info.valid_range_offset_start != 0 &&
|
2014-12-08 11:09:00 +08:00
|
|
|
function_info.valid_range_offset_end != 0) {
|
2016-05-25 12:20:28 +08:00
|
|
|
SectionList *sl = m_objfile.GetSectionList();
|
|
|
|
if (sl) {
|
|
|
|
addr_t func_range_start_file_addr =
|
|
|
|
function_info.valid_range_offset_start +
|
2018-12-11 23:21:15 +08:00
|
|
|
m_objfile.GetBaseAddress().GetFileAddress();
|
2014-12-08 11:09:00 +08:00
|
|
|
AddressRange func_range(func_range_start_file_addr,
|
|
|
|
function_info.valid_range_offset_end -
|
|
|
|
function_info.valid_range_offset_start,
|
|
|
|
sl);
|
2016-06-07 10:19:54 +08:00
|
|
|
unwind_plan.SetPlanValidAddressRange(func_range);
|
2014-12-08 11:09:00 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
|
2014-12-08 11:09:00 +08:00
|
|
|
if (arch.GetTriple().getArch() == llvm::Triple::x86_64) {
|
|
|
|
return CreateUnwindPlan_x86_64(target, function_info, unwind_plan,
|
2016-09-07 04:57:50 +08:00
|
|
|
addr);
|
|
|
|
}
|
2019-10-17 03:14:49 +08:00
|
|
|
if (arch.GetTriple().getArch() == llvm::Triple::aarch64 ||
|
|
|
|
arch.GetTriple().getArch() == llvm::Triple::aarch64_32) {
|
2016-05-25 12:20:28 +08:00
|
|
|
return CreateUnwindPlan_arm64(target, function_info, unwind_plan, addr);
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2014-12-08 11:09:00 +08:00
|
|
|
if (arch.GetTriple().getArch() == llvm::Triple::x86) {
|
|
|
|
return CreateUnwindPlan_i386(target, function_info, unwind_plan, addr);
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2016-06-07 10:19:54 +08:00
|
|
|
if (arch.GetTriple().getArch() == llvm::Triple::arm ||
|
|
|
|
arch.GetTriple().getArch() == llvm::Triple::thumb) {
|
|
|
|
return CreateUnwindPlan_armv7(target, function_info, unwind_plan, addr);
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2014-12-08 11:09:00 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2014-12-08 11:09:00 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-12-20 11:12:51 +08:00
|
|
|
bool CompactUnwindInfo::IsValid(const ProcessSP &process_sp) {
|
|
|
|
if (m_section_sp.get() == nullptr)
|
2014-12-08 11:09:00 +08:00
|
|
|
return false;
|
|
|
|
|
|
|
|
if (m_indexes_computed == eLazyBoolYes && m_unwindinfo_data_computed)
|
|
|
|
return true;
|
|
|
|
|
2014-12-20 11:12:51 +08:00
|
|
|
ScanIndex(process_sp);
|
2014-12-08 11:09:00 +08:00
|
|
|
|
|
|
|
return m_indexes_computed == eLazyBoolYes && m_unwindinfo_data_computed;
|
|
|
|
}
|
|
|
|
|
2014-12-20 11:12:51 +08:00
|
|
|
void CompactUnwindInfo::ScanIndex(const ProcessSP &process_sp) {
|
2016-05-19 13:13:57 +08:00
|
|
|
std::lock_guard<std::mutex> guard(m_mutex);
|
2014-12-08 11:09:00 +08:00
|
|
|
if (m_indexes_computed == eLazyBoolYes && m_unwindinfo_data_computed)
|
|
|
|
return;
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2014-12-08 11:09:00 +08:00
|
|
|
// We can't read the index for some reason.
|
|
|
|
if (m_indexes_computed == eLazyBoolNo) {
|
2016-09-07 04:57:50 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-12-21 18:44:54 +08:00
|
|
|
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND));
|
2016-09-07 04:57:50 +08:00
|
|
|
if (log)
|
2014-12-21 18:44:54 +08:00
|
|
|
m_objfile.GetModule()->LogMessage(
|
|
|
|
log, "Reading compact unwind first-level indexes");
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2018-12-15 08:15:33 +08:00
|
|
|
if (!m_unwindinfo_data_computed) {
|
2014-12-20 11:12:51 +08:00
|
|
|
if (m_section_sp->IsEncrypted()) {
|
|
|
|
// Can't get section contents of a protected/encrypted section until we
|
2018-05-01 00:49:04 +08:00
|
|
|
// have a live process and can read them out of memory.
|
2014-12-20 11:12:51 +08:00
|
|
|
if (process_sp.get() == nullptr)
|
2014-12-08 11:09:00 +08:00
|
|
|
return;
|
2019-02-12 07:13:08 +08:00
|
|
|
m_section_contents_if_encrypted =
|
|
|
|
std::make_shared<DataBufferHeap>(m_section_sp->GetByteSize(), 0);
|
2017-05-12 12:51:55 +08:00
|
|
|
Status error;
|
2014-12-20 11:12:51 +08:00
|
|
|
if (process_sp->ReadMemory(
|
2016-06-07 10:19:54 +08:00
|
|
|
m_section_sp->GetLoadBaseAddress(&process_sp->GetTarget()),
|
|
|
|
m_section_contents_if_encrypted->GetBytes(),
|
2014-12-20 11:12:51 +08:00
|
|
|
m_section_sp->GetByteSize(),
|
|
|
|
error) == m_section_sp->GetByteSize() &&
|
|
|
|
error.Success()) {
|
|
|
|
m_unwindinfo_data.SetAddressByteSize(
|
|
|
|
process_sp->GetTarget().GetArchitecture().GetAddressByteSize());
|
|
|
|
m_unwindinfo_data.SetByteOrder(
|
|
|
|
process_sp->GetTarget().GetArchitecture().GetByteOrder());
|
|
|
|
m_unwindinfo_data.SetData(m_section_contents_if_encrypted, 0);
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
} else {
|
2014-12-20 11:12:51 +08:00
|
|
|
m_objfile.ReadSectionData(m_section_sp.get(), m_unwindinfo_data);
|
2014-12-08 11:09:00 +08:00
|
|
|
}
|
2014-12-20 11:12:51 +08:00
|
|
|
if (m_unwindinfo_data.GetByteSize() != m_section_sp->GetByteSize())
|
2016-09-07 04:57:50 +08:00
|
|
|
return;
|
2014-12-08 11:09:00 +08:00
|
|
|
m_unwindinfo_data_computed = true;
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2014-12-08 11:09:00 +08:00
|
|
|
|
|
|
|
if (m_unwindinfo_data.GetByteSize() > 0) {
|
2014-12-20 11:12:51 +08:00
|
|
|
offset_t offset = 0;
|
2014-12-08 11:09:00 +08:00
|
|
|
|
|
|
|
// struct unwind_info_section_header
|
|
|
|
// {
|
|
|
|
// uint32_t version; // UNWIND_SECTION_VERSION
|
|
|
|
// uint32_t commonEncodingsArraySectionOffset;
|
|
|
|
// uint32_t commonEncodingsArrayCount;
|
|
|
|
// uint32_t personalityArraySectionOffset;
|
|
|
|
// uint32_t personalityArrayCount;
|
|
|
|
// uint32_t indexSectionOffset;
|
|
|
|
// uint32_t indexCount;
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2014-12-08 11:09:00 +08:00
|
|
|
m_unwind_header.version = m_unwindinfo_data.GetU32(&offset);
|
|
|
|
m_unwind_header.common_encodings_array_offset =
|
|
|
|
m_unwindinfo_data.GetU32(&offset);
|
|
|
|
m_unwind_header.common_encodings_array_count =
|
|
|
|
m_unwindinfo_data.GetU32(&offset);
|
|
|
|
m_unwind_header.personality_array_offset =
|
|
|
|
m_unwindinfo_data.GetU32(&offset);
|
|
|
|
m_unwind_header.personality_array_count = m_unwindinfo_data.GetU32(&offset);
|
|
|
|
uint32_t indexSectionOffset = m_unwindinfo_data.GetU32(&offset);
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2014-12-08 11:09:00 +08:00
|
|
|
uint32_t indexCount = m_unwindinfo_data.GetU32(&offset);
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2015-04-02 12:35:32 +08:00
|
|
|
if (m_unwind_header.common_encodings_array_offset >
|
|
|
|
m_unwindinfo_data.GetByteSize() ||
|
|
|
|
m_unwind_header.personality_array_offset >
|
2014-12-20 11:12:51 +08:00
|
|
|
m_unwindinfo_data.GetByteSize() ||
|
2015-04-02 12:35:32 +08:00
|
|
|
indexSectionOffset > m_unwindinfo_data.GetByteSize() ||
|
|
|
|
offset > m_unwindinfo_data.GetByteSize()) {
|
|
|
|
Host::SystemLog(Host::eSystemLogError, "error: Invalid offset "
|
|
|
|
"encountered in compact unwind "
|
|
|
|
"info, skipping\n");
|
|
|
|
// don't trust anything from this compact_unwind section if it looks
|
2015-07-22 08:16:02 +08:00
|
|
|
// blatantly invalid data in the header.
|
2014-12-08 11:09:00 +08:00
|
|
|
m_indexes_computed = eLazyBoolNo;
|
2015-04-02 12:35:32 +08:00
|
|
|
return;
|
2014-12-08 11:09:00 +08:00
|
|
|
}
|
|
|
|
|
2018-05-01 00:49:04 +08:00
|
|
|
// Parse the basic information from the indexes We wait to scan the second
|
|
|
|
// level page info until it's needed
|
2016-06-07 10:19:54 +08:00
|
|
|
|
2018-05-01 00:49:04 +08:00
|
|
|
// struct unwind_info_section_header_index_entry {
|
2014-12-08 11:09:00 +08:00
|
|
|
// uint32_t functionOffset;
|
|
|
|
// uint32_t secondLevelPagesSectionOffset;
|
|
|
|
// uint32_t lsdaIndexArraySectionOffset;
|
2016-09-07 04:57:50 +08:00
|
|
|
// };
|
|
|
|
|
2014-12-08 11:09:00 +08:00
|
|
|
bool clear_address_zeroth_bit = false;
|
2019-01-03 18:37:19 +08:00
|
|
|
if (ArchSpec arch = m_objfile.GetArchitecture()) {
|
2014-12-08 11:09:00 +08:00
|
|
|
if (arch.GetTriple().getArch() == llvm::Triple::arm ||
|
2016-06-07 10:19:54 +08:00
|
|
|
arch.GetTriple().getArch() == llvm::Triple::thumb)
|
2014-12-08 11:09:00 +08:00
|
|
|
clear_address_zeroth_bit = true;
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2014-12-08 11:09:00 +08:00
|
|
|
|
|
|
|
offset = indexSectionOffset;
|
|
|
|
for (uint32_t idx = 0; idx < indexCount; idx++) {
|
|
|
|
uint32_t function_offset =
|
|
|
|
m_unwindinfo_data.GetU32(&offset); // functionOffset
|
|
|
|
uint32_t second_level_offset =
|
|
|
|
m_unwindinfo_data.GetU32(&offset); // secondLevelPagesSectionOffset
|
|
|
|
uint32_t lsda_offset =
|
|
|
|
m_unwindinfo_data.GetU32(&offset); // lsdaIndexArraySectionOffset
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2014-12-08 11:09:00 +08:00
|
|
|
if (second_level_offset > m_section_sp->GetByteSize() ||
|
|
|
|
lsda_offset > m_section_sp->GetByteSize()) {
|
|
|
|
m_indexes_computed = eLazyBoolNo;
|
|
|
|
}
|
|
|
|
|
2016-06-07 10:19:54 +08:00
|
|
|
if (clear_address_zeroth_bit)
|
|
|
|
function_offset &= ~1ull;
|
|
|
|
|
2014-12-08 11:09:00 +08:00
|
|
|
UnwindIndex this_index;
|
2016-06-07 10:19:54 +08:00
|
|
|
this_index.function_offset = function_offset;
|
2014-12-08 11:09:00 +08:00
|
|
|
this_index.second_level = second_level_offset;
|
|
|
|
this_index.lsda_array_start = lsda_offset;
|
|
|
|
|
|
|
|
if (m_indexes.size() > 0) {
|
|
|
|
m_indexes[m_indexes.size() - 1].lsda_array_end = lsda_offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (second_level_offset == 0) {
|
|
|
|
this_index.sentinal_entry = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_indexes.push_back(this_index);
|
|
|
|
}
|
|
|
|
m_indexes_computed = eLazyBoolYes;
|
2016-09-07 04:57:50 +08:00
|
|
|
} else {
|
2014-12-08 11:09:00 +08:00
|
|
|
m_indexes_computed = eLazyBoolNo;
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2014-12-08 11:09:00 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t CompactUnwindInfo::GetLSDAForFunctionOffset(uint32_t lsda_offset,
|
|
|
|
uint32_t lsda_count,
|
|
|
|
uint32_t function_offset) {
|
2018-05-01 00:49:04 +08:00
|
|
|
// struct unwind_info_section_header_lsda_index_entry {
|
2014-12-08 11:09:00 +08:00
|
|
|
// uint32_t functionOffset;
|
|
|
|
// uint32_t lsdaOffset;
|
|
|
|
// };
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2014-12-08 11:09:00 +08:00
|
|
|
offset_t first_entry = lsda_offset;
|
|
|
|
uint32_t low = 0;
|
|
|
|
uint32_t high = lsda_count;
|
|
|
|
while (low < high) {
|
|
|
|
uint32_t mid = (low + high) / 2;
|
|
|
|
offset_t offset = first_entry + (mid * 8);
|
|
|
|
uint32_t mid_func_offset =
|
|
|
|
m_unwindinfo_data.GetU32(&offset); // functionOffset
|
|
|
|
uint32_t mid_lsda_offset = m_unwindinfo_data.GetU32(&offset); // lsdaOffset
|
|
|
|
if (mid_func_offset == function_offset) {
|
|
|
|
return mid_lsda_offset;
|
|
|
|
}
|
|
|
|
if (mid_func_offset < function_offset) {
|
|
|
|
low = mid + 1;
|
2016-09-07 04:57:50 +08:00
|
|
|
} else {
|
2014-12-08 11:09:00 +08:00
|
|
|
high = mid;
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
}
|
2014-12-08 11:09:00 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-12-21 18:44:54 +08:00
|
|
|
lldb::offset_t 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) {
|
2014-12-08 11:09:00 +08:00
|
|
|
// typedef uint32_t compact_unwind_encoding_t;
|
2018-05-01 00:49:04 +08:00
|
|
|
// struct unwind_info_regular_second_level_entry {
|
2014-12-08 11:09:00 +08:00
|
|
|
// uint32_t functionOffset;
|
|
|
|
// compact_unwind_encoding_t encoding;
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2014-12-08 11:09:00 +08:00
|
|
|
offset_t first_entry = entry_page_offset;
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2014-12-08 11:09:00 +08:00
|
|
|
uint32_t low = 0;
|
|
|
|
uint32_t high = entry_count;
|
|
|
|
uint32_t last = high - 1;
|
|
|
|
while (low < high) {
|
|
|
|
uint32_t mid = (low + high) / 2;
|
|
|
|
offset_t offset = first_entry + (mid * 8);
|
|
|
|
uint32_t mid_func_offset =
|
|
|
|
m_unwindinfo_data.GetU32(&offset); // functionOffset
|
2014-12-21 18:44:54 +08:00
|
|
|
uint32_t next_func_offset = 0;
|
2014-12-08 11:09:00 +08:00
|
|
|
if (mid < last) {
|
|
|
|
offset = first_entry + ((mid + 1) * 8);
|
|
|
|
next_func_offset = m_unwindinfo_data.GetU32(&offset); // functionOffset
|
|
|
|
}
|
|
|
|
if (mid_func_offset <= function_offset) {
|
|
|
|
if (mid == last || (next_func_offset > function_offset)) {
|
2014-12-21 18:44:54 +08:00
|
|
|
if (entry_func_start_offset)
|
|
|
|
*entry_func_start_offset = mid_func_offset;
|
|
|
|
if (mid != last && entry_func_end_offset)
|
|
|
|
*entry_func_end_offset = next_func_offset;
|
2014-12-08 11:09:00 +08:00
|
|
|
return first_entry + (mid * 8);
|
2016-09-07 04:57:50 +08:00
|
|
|
} else {
|
2014-12-08 11:09:00 +08:00
|
|
|
low = mid + 1;
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
} else {
|
2014-12-08 11:09:00 +08:00
|
|
|
high = mid;
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
}
|
2014-12-08 11:09:00 +08:00
|
|
|
return LLDB_INVALID_OFFSET;
|
|
|
|
}
|
|
|
|
|
2014-12-21 18:44:54 +08:00
|
|
|
uint32_t 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) {
|
2014-12-08 11:09:00 +08:00
|
|
|
offset_t first_entry = entry_page_offset;
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2014-12-08 11:09:00 +08:00
|
|
|
uint32_t low = 0;
|
|
|
|
uint32_t high = entry_count;
|
|
|
|
uint32_t last = high - 1;
|
|
|
|
while (low < high) {
|
|
|
|
uint32_t mid = (low + high) / 2;
|
|
|
|
offset_t offset = first_entry + (mid * 4);
|
|
|
|
uint32_t entry = m_unwindinfo_data.GetU32(&offset); // entry
|
|
|
|
uint32_t mid_func_offset = UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET(entry);
|
|
|
|
mid_func_offset += function_offset_base;
|
|
|
|
uint32_t next_func_offset = 0;
|
|
|
|
if (mid < last) {
|
|
|
|
offset = first_entry + ((mid + 1) * 4);
|
|
|
|
uint32_t next_entry = m_unwindinfo_data.GetU32(&offset); // entry
|
|
|
|
next_func_offset = UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET(next_entry);
|
|
|
|
next_func_offset += function_offset_base;
|
|
|
|
}
|
|
|
|
if (mid_func_offset <= function_offset_to_find) {
|
|
|
|
if (mid == last || (next_func_offset > function_offset_to_find)) {
|
2014-12-21 18:44:54 +08:00
|
|
|
if (entry_func_start_offset)
|
|
|
|
*entry_func_start_offset = mid_func_offset;
|
|
|
|
if (mid != last && entry_func_end_offset)
|
|
|
|
*entry_func_end_offset = next_func_offset;
|
2014-12-08 11:09:00 +08:00
|
|
|
return UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX(entry);
|
|
|
|
} else {
|
|
|
|
low = mid + 1;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
high = mid;
|
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2014-12-08 11:09:00 +08:00
|
|
|
|
|
|
|
return UINT32_MAX;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CompactUnwindInfo::GetCompactUnwindInfoForFunction(
|
|
|
|
Target &target, Address address, FunctionInfo &unwind_info) {
|
|
|
|
unwind_info.encoding = 0;
|
|
|
|
unwind_info.lsda_address.Clear();
|
|
|
|
unwind_info.personality_ptr_address.Clear();
|
|
|
|
|
2014-12-20 11:12:51 +08:00
|
|
|
if (!IsValid(target.GetProcessSP()))
|
2014-12-08 11:09:00 +08:00
|
|
|
return false;
|
|
|
|
|
|
|
|
addr_t text_section_file_address = LLDB_INVALID_ADDRESS;
|
|
|
|
SectionList *sl = m_objfile.GetSectionList();
|
|
|
|
if (sl) {
|
|
|
|
SectionSP text_sect = sl->FindSectionByType(eSectionTypeCode, true);
|
|
|
|
if (text_sect.get()) {
|
|
|
|
text_section_file_address = text_sect->GetFileAddress();
|
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2014-12-08 11:09:00 +08:00
|
|
|
if (text_section_file_address == LLDB_INVALID_ADDRESS)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
addr_t function_offset =
|
2018-12-11 23:21:15 +08:00
|
|
|
address.GetFileAddress() - m_objfile.GetBaseAddress().GetFileAddress();
|
2016-06-07 10:19:54 +08:00
|
|
|
|
2014-12-08 11:09:00 +08:00
|
|
|
UnwindIndex key;
|
|
|
|
key.function_offset = function_offset;
|
2016-06-07 10:19:54 +08:00
|
|
|
|
2014-12-08 11:09:00 +08:00
|
|
|
std::vector<UnwindIndex>::const_iterator it;
|
|
|
|
it = std::lower_bound(m_indexes.begin(), m_indexes.end(), key);
|
|
|
|
if (it == m_indexes.end()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (it->function_offset != key.function_offset) {
|
|
|
|
if (it != m_indexes.begin())
|
|
|
|
--it;
|
|
|
|
}
|
|
|
|
|
2018-12-15 08:15:33 +08:00
|
|
|
if (it->sentinal_entry) {
|
2014-12-08 11:09:00 +08:00
|
|
|
return false;
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
|
2014-12-21 18:44:54 +08:00
|
|
|
auto next_it = it + 1;
|
2015-06-19 05:15:58 +08:00
|
|
|
if (next_it != m_indexes.end()) {
|
2018-05-01 00:49:04 +08:00
|
|
|
// initialize the function offset end range to be the start of the next
|
|
|
|
// index offset. If we find an entry which is at the end of the index
|
|
|
|
// table, this will establish the range end.
|
2014-12-21 18:44:54 +08:00
|
|
|
unwind_info.valid_range_offset_end = next_it->function_offset;
|
2014-12-08 11:09:00 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2014-12-08 11:09:00 +08:00
|
|
|
offset_t second_page_offset = it->second_level;
|
|
|
|
offset_t lsda_array_start = it->lsda_array_start;
|
|
|
|
offset_t lsda_array_count = (it->lsda_array_end - it->lsda_array_start) / 8;
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2014-12-08 11:09:00 +08:00
|
|
|
offset_t offset = second_page_offset;
|
|
|
|
uint32_t kind = m_unwindinfo_data.GetU32(
|
|
|
|
&offset); // UNWIND_SECOND_LEVEL_REGULAR or UNWIND_SECOND_LEVEL_COMPRESSED
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2014-12-08 11:09:00 +08:00
|
|
|
if (kind == UNWIND_SECOND_LEVEL_REGULAR) {
|
2018-05-01 00:49:04 +08:00
|
|
|
// struct unwind_info_regular_second_level_page_header {
|
2014-12-08 11:09:00 +08:00
|
|
|
// uint32_t kind; // UNWIND_SECOND_LEVEL_REGULAR
|
|
|
|
// uint16_t entryPageOffset;
|
|
|
|
// uint16_t entryCount;
|
|
|
|
|
2016-06-07 10:19:54 +08:00
|
|
|
// typedef uint32_t compact_unwind_encoding_t;
|
2018-05-01 00:49:04 +08:00
|
|
|
// struct unwind_info_regular_second_level_entry {
|
2014-12-21 18:44:54 +08:00
|
|
|
// uint32_t functionOffset;
|
|
|
|
// compact_unwind_encoding_t encoding;
|
|
|
|
|
2014-12-08 11:09:00 +08:00
|
|
|
uint16_t entry_page_offset =
|
|
|
|
m_unwindinfo_data.GetU16(&offset); // entryPageOffset
|
|
|
|
uint16_t entry_count = m_unwindinfo_data.GetU16(&offset); // entryCount
|
|
|
|
|
2014-12-21 18:44:54 +08:00
|
|
|
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);
|
2014-12-08 11:09:00 +08:00
|
|
|
if (entry_offset == LLDB_INVALID_OFFSET) {
|
|
|
|
return false;
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2014-12-08 11:09:00 +08:00
|
|
|
entry_offset += 4; // skip over functionOffset
|
|
|
|
unwind_info.encoding = m_unwindinfo_data.GetU32(&entry_offset); // encoding
|
|
|
|
if (unwind_info.encoding & UNWIND_HAS_LSDA) {
|
|
|
|
SectionList *sl = m_objfile.GetSectionList();
|
|
|
|
if (sl) {
|
|
|
|
uint32_t lsda_offset = GetLSDAForFunctionOffset(
|
|
|
|
lsda_array_start, lsda_array_count, function_offset);
|
2018-12-11 23:21:15 +08:00
|
|
|
addr_t objfile_base_address =
|
|
|
|
m_objfile.GetBaseAddress().GetFileAddress();
|
2014-12-08 11:09:00 +08:00
|
|
|
unwind_info.lsda_address.ResolveAddressUsingFileSections(
|
2018-12-11 23:21:15 +08:00
|
|
|
objfile_base_address + lsda_offset, sl);
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
}
|
2014-12-08 11:09:00 +08:00
|
|
|
if (unwind_info.encoding & UNWIND_PERSONALITY_MASK) {
|
|
|
|
uint32_t personality_index =
|
|
|
|
EXTRACT_BITS(unwind_info.encoding, UNWIND_PERSONALITY_MASK);
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2014-12-08 11:09:00 +08:00
|
|
|
if (personality_index > 0) {
|
|
|
|
personality_index--;
|
|
|
|
if (personality_index < m_unwind_header.personality_array_count) {
|
|
|
|
offset_t offset = m_unwind_header.personality_array_offset;
|
|
|
|
offset += 4 * personality_index;
|
|
|
|
SectionList *sl = m_objfile.GetSectionList();
|
|
|
|
if (sl) {
|
|
|
|
uint32_t personality_offset = m_unwindinfo_data.GetU32(&offset);
|
2018-12-11 23:21:15 +08:00
|
|
|
addr_t objfile_base_address =
|
|
|
|
m_objfile.GetBaseAddress().GetFileAddress();
|
2014-12-08 11:09:00 +08:00
|
|
|
unwind_info.personality_ptr_address.ResolveAddressUsingFileSections(
|
2018-12-11 23:21:15 +08:00
|
|
|
objfile_base_address + personality_offset, sl);
|
2014-12-08 11:09:00 +08:00
|
|
|
}
|
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
}
|
2014-12-08 11:09:00 +08:00
|
|
|
return true;
|
|
|
|
} else if (kind == UNWIND_SECOND_LEVEL_COMPRESSED) {
|
2018-05-01 00:49:04 +08:00
|
|
|
// struct unwind_info_compressed_second_level_page_header {
|
2014-12-08 11:09:00 +08:00
|
|
|
// uint32_t kind; // UNWIND_SECOND_LEVEL_COMPRESSED
|
|
|
|
// uint16_t entryPageOffset; // offset from this 2nd lvl page
|
|
|
|
// idx to array of entries
|
|
|
|
// // (an entry has a function
|
|
|
|
// offset and index into the
|
|
|
|
// encodings)
|
2016-06-07 10:19:54 +08:00
|
|
|
// // NB function offset from the
|
|
|
|
// entry in the compressed page
|
2014-12-08 11:09:00 +08:00
|
|
|
// // must be added to the index's
|
|
|
|
// functionOffset value.
|
|
|
|
// uint16_t entryCount;
|
|
|
|
// uint16_t encodingsPageOffset; // offset from this 2nd lvl page
|
|
|
|
// idx to array of encodings
|
|
|
|
// uint16_t encodingsCount;
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2014-12-08 11:09:00 +08:00
|
|
|
uint16_t entry_page_offset =
|
|
|
|
m_unwindinfo_data.GetU16(&offset); // entryPageOffset
|
|
|
|
uint16_t entry_count = m_unwindinfo_data.GetU16(&offset); // entryCount
|
|
|
|
uint16_t encodings_page_offset =
|
|
|
|
m_unwindinfo_data.GetU16(&offset); // encodingsPageOffset
|
|
|
|
uint16_t encodings_count =
|
|
|
|
m_unwindinfo_data.GetU16(&offset); // encodingsCount
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2014-12-08 11:09:00 +08:00
|
|
|
uint32_t encoding_index = BinarySearchCompressedSecondPage(
|
2014-12-21 18:44:54 +08:00
|
|
|
second_page_offset + entry_page_offset, entry_count, function_offset,
|
2014-12-08 11:09:00 +08:00
|
|
|
it->function_offset, &unwind_info.valid_range_offset_start,
|
2014-12-21 18:44:54 +08:00
|
|
|
&unwind_info.valid_range_offset_end);
|
2014-12-08 11:09:00 +08:00
|
|
|
if (encoding_index == UINT32_MAX ||
|
|
|
|
encoding_index >=
|
|
|
|
encodings_count + m_unwind_header.common_encodings_array_count) {
|
|
|
|
return false;
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2014-12-08 11:09:00 +08:00
|
|
|
uint32_t encoding = 0;
|
|
|
|
if (encoding_index < m_unwind_header.common_encodings_array_count) {
|
|
|
|
offset = m_unwind_header.common_encodings_array_offset +
|
|
|
|
(encoding_index * sizeof(uint32_t));
|
|
|
|
encoding = m_unwindinfo_data.GetU32(
|
|
|
|
&offset); // encoding entry from the commonEncodingsArray
|
2016-09-07 04:57:50 +08:00
|
|
|
} else {
|
2014-12-08 11:09:00 +08:00
|
|
|
uint32_t page_specific_entry_index =
|
|
|
|
encoding_index - m_unwind_header.common_encodings_array_count;
|
|
|
|
offset = second_page_offset + encodings_page_offset +
|
|
|
|
(page_specific_entry_index * sizeof(uint32_t));
|
|
|
|
encoding = m_unwindinfo_data.GetU32(
|
|
|
|
&offset); // encoding entry from the page-specific encoding array
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2014-12-08 11:09:00 +08:00
|
|
|
if (encoding == 0)
|
|
|
|
return false;
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2014-12-08 11:09:00 +08:00
|
|
|
unwind_info.encoding = encoding;
|
|
|
|
if (unwind_info.encoding & UNWIND_HAS_LSDA) {
|
|
|
|
SectionList *sl = m_objfile.GetSectionList();
|
2016-09-07 04:57:50 +08:00
|
|
|
if (sl) {
|
2014-12-08 11:09:00 +08:00
|
|
|
uint32_t lsda_offset = GetLSDAForFunctionOffset(
|
|
|
|
lsda_array_start, lsda_array_count, function_offset);
|
2018-12-11 23:21:15 +08:00
|
|
|
addr_t objfile_base_address =
|
|
|
|
m_objfile.GetBaseAddress().GetFileAddress();
|
2014-12-08 11:09:00 +08:00
|
|
|
unwind_info.lsda_address.ResolveAddressUsingFileSections(
|
2018-12-11 23:21:15 +08:00
|
|
|
objfile_base_address + lsda_offset, sl);
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
}
|
2014-12-08 11:09:00 +08:00
|
|
|
if (unwind_info.encoding & UNWIND_PERSONALITY_MASK) {
|
|
|
|
uint32_t personality_index =
|
|
|
|
EXTRACT_BITS(unwind_info.encoding, UNWIND_PERSONALITY_MASK);
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2014-12-08 11:09:00 +08:00
|
|
|
if (personality_index > 0) {
|
|
|
|
personality_index--;
|
|
|
|
if (personality_index < m_unwind_header.personality_array_count) {
|
|
|
|
offset_t offset = m_unwind_header.personality_array_offset;
|
|
|
|
offset += 4 * personality_index;
|
|
|
|
SectionList *sl = m_objfile.GetSectionList();
|
|
|
|
if (sl) {
|
|
|
|
uint32_t personality_offset = m_unwindinfo_data.GetU32(&offset);
|
2018-12-11 23:21:15 +08:00
|
|
|
addr_t objfile_base_address =
|
|
|
|
m_objfile.GetBaseAddress().GetFileAddress();
|
2014-12-08 11:09:00 +08:00
|
|
|
unwind_info.personality_ptr_address.ResolveAddressUsingFileSections(
|
2018-12-11 23:21:15 +08:00
|
|
|
objfile_base_address + personality_offset, sl);
|
2014-12-08 11:09:00 +08:00
|
|
|
}
|
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2014-12-08 11:09:00 +08:00
|
|
|
}
|
|
|
|
return true;
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2014-12-08 11:09:00 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
enum x86_64_eh_regnum {
|
|
|
|
rax = 0,
|
|
|
|
rdx = 1,
|
|
|
|
rcx = 2,
|
|
|
|
rbx = 3,
|
|
|
|
rsi = 4,
|
|
|
|
rdi = 5,
|
|
|
|
rbp = 6,
|
|
|
|
rsp = 7,
|
|
|
|
r8 = 8,
|
|
|
|
r9 = 9,
|
|
|
|
r10 = 10,
|
|
|
|
r11 = 11,
|
|
|
|
r12 = 12,
|
|
|
|
r13 = 13,
|
|
|
|
r14 = 14,
|
|
|
|
r15 = 15,
|
|
|
|
rip = 16 // this is officially the Return Address register number, but close
|
|
|
|
// enough
|
|
|
|
};
|
|
|
|
|
2018-05-01 00:49:04 +08:00
|
|
|
// Convert the compact_unwind_info.h register numbering scheme to
|
|
|
|
// eRegisterKindEHFrame (eh_frame) register numbering scheme.
|
2014-12-08 11:09:00 +08:00
|
|
|
uint32_t translate_to_eh_frame_regnum_x86_64(uint32_t unwind_regno) {
|
|
|
|
switch (unwind_regno) {
|
|
|
|
case UNWIND_X86_64_REG_RBX:
|
|
|
|
return x86_64_eh_regnum::rbx;
|
|
|
|
case UNWIND_X86_64_REG_R12:
|
|
|
|
return x86_64_eh_regnum::r12;
|
|
|
|
case UNWIND_X86_64_REG_R13:
|
|
|
|
return x86_64_eh_regnum::r13;
|
|
|
|
case UNWIND_X86_64_REG_R14:
|
|
|
|
return x86_64_eh_regnum::r14;
|
|
|
|
case UNWIND_X86_64_REG_R15:
|
|
|
|
return x86_64_eh_regnum::r15;
|
|
|
|
case UNWIND_X86_64_REG_RBP:
|
|
|
|
return x86_64_eh_regnum::rbp;
|
|
|
|
default:
|
|
|
|
return LLDB_INVALID_REGNUM;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CompactUnwindInfo::CreateUnwindPlan_x86_64(Target &target,
|
|
|
|
FunctionInfo &function_info,
|
|
|
|
UnwindPlan &unwind_plan,
|
|
|
|
Address pc_or_function_start) {
|
|
|
|
unwind_plan.SetSourceName("compact unwind info");
|
|
|
|
unwind_plan.SetSourcedFromCompiler(eLazyBoolYes);
|
|
|
|
unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
|
Support Linux signal return trampolines in frame initialization
Summary:
Add __kernel_rt_sigreturn to the list of trap handlers for Linux (it's
used as such on aarch64 at least), and __restore_rt as well (used on
x86_64).
Skip decrement-and-recompute for trap handlers in
InitializeNonZerothFrame, as signal dispatch may point the child frame's
return address to the start of the return trampoline.
Parse the 'S' flag for signal handlers from eh_frame augmentation, and
propagate it to the unwind plan.
Reviewers: labath, jankratochvil, compnerd, jfb, jasonmolenda
Reviewed By: jasonmolenda
Subscribers: clayborg, MaskRay, wuzish, nemanjai, kbarton, jrtc27, atanasyan, jsji, javed.absar, kristof.beyls, lldb-commits
Tags: #lldb
Differential Revision: https://reviews.llvm.org/D63667
llvm-svn: 366580
2019-07-19 22:05:55 +08:00
|
|
|
unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo);
|
2015-08-15 09:21:01 +08:00
|
|
|
unwind_plan.SetRegisterKind(eRegisterKindEHFrame);
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2014-12-08 11:09:00 +08:00
|
|
|
unwind_plan.SetLSDAAddress(function_info.lsda_address);
|
|
|
|
unwind_plan.SetPersonalityFunctionPtr(function_info.personality_ptr_address);
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2014-12-08 11:09:00 +08:00
|
|
|
UnwindPlan::RowSP row(new UnwindPlan::Row);
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2014-12-08 11:09:00 +08:00
|
|
|
const int wordsize = 8;
|
|
|
|
int mode = function_info.encoding & UNWIND_X86_64_MODE_MASK;
|
|
|
|
switch (mode) {
|
|
|
|
case UNWIND_X86_64_MODE_RBP_FRAME: {
|
2015-02-23 18:19:16 +08:00
|
|
|
row->GetCFAValue().SetIsRegisterPlusOffset(
|
|
|
|
translate_to_eh_frame_regnum_x86_64(UNWIND_X86_64_REG_RBP),
|
|
|
|
2 * wordsize);
|
2014-12-08 11:09:00 +08:00
|
|
|
row->SetOffset(0);
|
|
|
|
row->SetRegisterLocationToAtCFAPlusOffset(x86_64_eh_regnum::rbp,
|
|
|
|
wordsize * -2, true);
|
|
|
|
row->SetRegisterLocationToAtCFAPlusOffset(x86_64_eh_regnum::rip,
|
|
|
|
wordsize * -1, true);
|
|
|
|
row->SetRegisterLocationToIsCFAPlusOffset(x86_64_eh_regnum::rsp, 0, true);
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2014-12-08 11:09:00 +08:00
|
|
|
uint32_t saved_registers_offset =
|
|
|
|
EXTRACT_BITS(function_info.encoding, UNWIND_X86_64_RBP_FRAME_OFFSET);
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2014-12-08 11:09:00 +08:00
|
|
|
uint32_t saved_registers_locations =
|
|
|
|
EXTRACT_BITS(function_info.encoding, UNWIND_X86_64_RBP_FRAME_REGISTERS);
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2014-12-08 11:09:00 +08:00
|
|
|
saved_registers_offset += 2;
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2014-12-08 11:09:00 +08:00
|
|
|
for (int i = 0; i < 5; i++) {
|
|
|
|
uint32_t regnum = saved_registers_locations & 0x7;
|
|
|
|
switch (regnum) {
|
|
|
|
case UNWIND_X86_64_REG_NONE:
|
|
|
|
break;
|
|
|
|
case UNWIND_X86_64_REG_RBX:
|
|
|
|
case UNWIND_X86_64_REG_R12:
|
|
|
|
case UNWIND_X86_64_REG_R13:
|
|
|
|
case UNWIND_X86_64_REG_R14:
|
|
|
|
case UNWIND_X86_64_REG_R15:
|
|
|
|
row->SetRegisterLocationToAtCFAPlusOffset(
|
|
|
|
translate_to_eh_frame_regnum_x86_64(regnum),
|
|
|
|
wordsize * -saved_registers_offset, true);
|
|
|
|
break;
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2014-12-08 11:09:00 +08:00
|
|
|
saved_registers_offset--;
|
|
|
|
saved_registers_locations >>= 3;
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2014-12-08 11:09:00 +08:00
|
|
|
unwind_plan.AppendRow(row);
|
|
|
|
return true;
|
2016-09-07 04:57:50 +08:00
|
|
|
} break;
|
2014-12-08 11:09:00 +08:00
|
|
|
|
|
|
|
case UNWIND_X86_64_MODE_STACK_IND: {
|
|
|
|
// The clang in Xcode 6 is emitting incorrect compact unwind encodings for
|
2018-05-01 00:49:04 +08:00
|
|
|
// this style of unwind. It was fixed in llvm r217020. The clang in Xcode
|
|
|
|
// 7 has this fixed.
|
2014-12-08 11:09:00 +08:00
|
|
|
return false;
|
2016-09-07 04:57:50 +08:00
|
|
|
} break;
|
|
|
|
|
2014-12-08 11:09:00 +08:00
|
|
|
case UNWIND_X86_64_MODE_STACK_IMMD: {
|
2014-12-22 19:02:02 +08:00
|
|
|
uint32_t stack_size = EXTRACT_BITS(function_info.encoding,
|
|
|
|
UNWIND_X86_64_FRAMELESS_STACK_SIZE);
|
|
|
|
uint32_t register_count = EXTRACT_BITS(
|
|
|
|
function_info.encoding, UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT);
|
|
|
|
uint32_t permutation = EXTRACT_BITS(
|
|
|
|
function_info.encoding, UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION);
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2014-12-22 19:02:02 +08:00
|
|
|
if (mode == UNWIND_X86_64_MODE_STACK_IND &&
|
|
|
|
function_info.valid_range_offset_start != 0) {
|
|
|
|
uint32_t stack_adjust = EXTRACT_BITS(
|
|
|
|
function_info.encoding, UNWIND_X86_64_FRAMELESS_STACK_ADJUST);
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2014-12-08 11:09:00 +08:00
|
|
|
// offset into the function instructions; 0 == beginning of first
|
|
|
|
// instruction
|
2014-12-22 19:02:02 +08:00
|
|
|
uint32_t offset_to_subl_insn = EXTRACT_BITS(
|
|
|
|
function_info.encoding, UNWIND_X86_64_FRAMELESS_STACK_SIZE);
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2014-12-22 19:02:02 +08:00
|
|
|
SectionList *sl = m_objfile.GetSectionList();
|
2016-09-07 04:57:50 +08:00
|
|
|
if (sl) {
|
2014-12-22 19:02:02 +08:00
|
|
|
ProcessSP process_sp = target.GetProcessSP();
|
|
|
|
if (process_sp) {
|
|
|
|
Address subl_payload_addr(function_info.valid_range_offset_start, sl);
|
|
|
|
subl_payload_addr.Slide(offset_to_subl_insn);
|
2017-05-12 12:51:55 +08:00
|
|
|
Status error;
|
2014-12-22 19:02:02 +08:00
|
|
|
uint64_t large_stack_size = process_sp->ReadUnsignedIntegerFromMemory(
|
|
|
|
subl_payload_addr.GetLoadAddress(&target), 4, 0, error);
|
|
|
|
if (large_stack_size != 0 && error.Success()) {
|
|
|
|
// Got the large stack frame size correctly - use it
|
|
|
|
stack_size = large_stack_size + (stack_adjust * wordsize);
|
2016-09-07 04:57:50 +08:00
|
|
|
} else {
|
2014-12-08 11:09:00 +08:00
|
|
|
return false;
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
} else {
|
2014-12-08 11:09:00 +08:00
|
|
|
return false;
|
|
|
|
}
|
2014-12-22 19:02:02 +08:00
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2014-12-08 11:09:00 +08:00
|
|
|
|
2015-02-23 18:19:16 +08:00
|
|
|
int32_t offset = mode == UNWIND_X86_64_MODE_STACK_IND
|
|
|
|
? stack_size
|
|
|
|
: stack_size * wordsize;
|
|
|
|
row->GetCFAValue().SetIsRegisterPlusOffset(x86_64_eh_regnum::rsp, offset);
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2014-12-22 19:02:02 +08:00
|
|
|
row->SetOffset(0);
|
|
|
|
row->SetRegisterLocationToAtCFAPlusOffset(x86_64_eh_regnum::rip,
|
|
|
|
wordsize * -1, true);
|
|
|
|
row->SetRegisterLocationToIsCFAPlusOffset(x86_64_eh_regnum::rsp, 0, true);
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2014-12-22 19:02:02 +08:00
|
|
|
if (register_count > 0) {
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2018-05-01 00:49:04 +08:00
|
|
|
// We need to include (up to) 6 registers in 10 bits. That would be 18
|
|
|
|
// bits if we just used 3 bits per reg to indicate the order they're
|
|
|
|
// saved on the stack.
|
2014-12-08 11:09:00 +08:00
|
|
|
//
|
|
|
|
// This is done with Lehmer code permutation, e.g. see
|
2018-05-01 00:49:04 +08:00
|
|
|
// http://stackoverflow.com/questions/1506078/fast-permutation-number-
|
|
|
|
// permutation-mapping-algorithms
|
2015-05-05 10:05:53 +08:00
|
|
|
int permunreg[6] = {0, 0, 0, 0, 0, 0};
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2018-05-01 00:49:04 +08:00
|
|
|
// This decodes the variable-base number in the 10 bits and gives us the
|
|
|
|
// Lehmer code sequence which can then be decoded.
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2016-06-07 10:19:54 +08:00
|
|
|
switch (register_count) {
|
2014-12-08 11:09:00 +08:00
|
|
|
case 6:
|
|
|
|
permunreg[0] = permutation / 120; // 120 == 5!
|
|
|
|
permutation -= (permunreg[0] * 120);
|
|
|
|
permunreg[1] = permutation / 24; // 24 == 4!
|
|
|
|
permutation -= (permunreg[1] * 24);
|
|
|
|
permunreg[2] = permutation / 6; // 6 == 3!
|
|
|
|
permutation -= (permunreg[2] * 6);
|
|
|
|
permunreg[3] = permutation / 2; // 2 == 2!
|
|
|
|
permutation -= (permunreg[3] * 2);
|
|
|
|
permunreg[4] = permutation; // 1 == 1!
|
|
|
|
permunreg[5] = 0;
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
permunreg[0] = permutation / 120;
|
|
|
|
permutation -= (permunreg[0] * 120);
|
|
|
|
permunreg[1] = permutation / 24;
|
|
|
|
permutation -= (permunreg[1] * 24);
|
|
|
|
permunreg[2] = permutation / 6;
|
|
|
|
permutation -= (permunreg[2] * 6);
|
|
|
|
permunreg[3] = permutation / 2;
|
2014-12-22 19:02:02 +08:00
|
|
|
permutation -= (permunreg[3] * 2);
|
2014-12-08 11:09:00 +08:00
|
|
|
permunreg[4] = permutation;
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
permunreg[0] = permutation / 60;
|
|
|
|
permutation -= (permunreg[0] * 60);
|
|
|
|
permunreg[1] = permutation / 12;
|
|
|
|
permutation -= (permunreg[1] * 12);
|
2014-12-22 19:02:02 +08:00
|
|
|
permunreg[2] = permutation / 3;
|
2014-12-08 11:09:00 +08:00
|
|
|
permutation -= (permunreg[2] * 3);
|
|
|
|
permunreg[3] = permutation;
|
2016-09-07 04:57:50 +08:00
|
|
|
break;
|
|
|
|
case 3:
|
2014-12-08 11:09:00 +08:00
|
|
|
permunreg[0] = permutation / 20;
|
|
|
|
permutation -= (permunreg[0] * 20);
|
|
|
|
permunreg[1] = permutation / 4;
|
|
|
|
permutation -= (permunreg[1] * 4);
|
2015-05-05 10:05:53 +08:00
|
|
|
permunreg[2] = permutation;
|
2014-12-08 11:09:00 +08:00
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
permunreg[0] = permutation / 5;
|
2014-12-29 21:03:19 +08:00
|
|
|
permutation -= (permunreg[0] * 5);
|
2014-12-08 11:09:00 +08:00
|
|
|
permunreg[1] = permutation;
|
|
|
|
break;
|
2016-09-07 04:57:50 +08:00
|
|
|
case 1:
|
2014-12-22 19:02:02 +08:00
|
|
|
permunreg[0] = permutation;
|
2016-09-07 04:57:50 +08:00
|
|
|
break;
|
2014-12-08 11:09:00 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2018-05-01 00:49:04 +08:00
|
|
|
// Decode the Lehmer code for this permutation of the registers v.
|
|
|
|
// http://en.wikipedia.org/wiki/Lehmer_code
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2014-12-08 11:09:00 +08:00
|
|
|
int registers[6] = {UNWIND_X86_64_REG_NONE, UNWIND_X86_64_REG_NONE,
|
2015-05-05 10:05:53 +08:00
|
|
|
UNWIND_X86_64_REG_NONE, UNWIND_X86_64_REG_NONE,
|
2014-12-08 11:09:00 +08:00
|
|
|
UNWIND_X86_64_REG_NONE, UNWIND_X86_64_REG_NONE};
|
|
|
|
bool used[7] = {false, false, false, false, false, false, false};
|
|
|
|
for (uint32_t i = 0; i < register_count; i++) {
|
|
|
|
int renum = 0;
|
|
|
|
for (int j = 1; j < 7; j++) {
|
2018-12-15 08:15:33 +08:00
|
|
|
if (!used[j]) {
|
2015-01-23 09:02:32 +08:00
|
|
|
if (renum == permunreg[i]) {
|
|
|
|
registers[i] = j;
|
|
|
|
used[j] = true;
|
2014-12-22 19:02:02 +08:00
|
|
|
break;
|
2014-12-08 11:09:00 +08:00
|
|
|
}
|
2014-12-22 19:02:02 +08:00
|
|
|
renum++;
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2014-12-08 11:09:00 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2014-12-08 11:09:00 +08:00
|
|
|
|
|
|
|
uint32_t saved_registers_offset = 1;
|
|
|
|
saved_registers_offset++;
|
|
|
|
|
|
|
|
for (int i = (sizeof(registers) / sizeof(int)) - 1; i >= 0; i--) {
|
|
|
|
switch (registers[i]) {
|
|
|
|
case UNWIND_X86_64_REG_NONE:
|
|
|
|
break;
|
|
|
|
case UNWIND_X86_64_REG_RBX:
|
|
|
|
case UNWIND_X86_64_REG_R12:
|
|
|
|
case UNWIND_X86_64_REG_R13:
|
|
|
|
case UNWIND_X86_64_REG_R14:
|
|
|
|
case UNWIND_X86_64_REG_R15:
|
|
|
|
case UNWIND_X86_64_REG_RBP:
|
|
|
|
row->SetRegisterLocationToAtCFAPlusOffset(
|
2015-01-23 09:02:32 +08:00
|
|
|
translate_to_eh_frame_regnum_x86_64(registers[i]),
|
2014-12-08 11:09:00 +08:00
|
|
|
wordsize * -saved_registers_offset, true);
|
2015-01-23 09:02:32 +08:00
|
|
|
saved_registers_offset++;
|
2016-09-07 04:57:50 +08:00
|
|
|
break;
|
2014-12-08 11:09:00 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2014-12-08 11:09:00 +08:00
|
|
|
}
|
2014-12-22 19:02:02 +08:00
|
|
|
unwind_plan.AppendRow(row);
|
2014-12-08 11:09:00 +08:00
|
|
|
return true;
|
2016-09-07 04:57:50 +08:00
|
|
|
} break;
|
|
|
|
|
2014-12-08 11:09:00 +08:00
|
|
|
case UNWIND_X86_64_MODE_DWARF: {
|
|
|
|
return false;
|
2016-09-07 04:57:50 +08:00
|
|
|
} break;
|
|
|
|
|
|
|
|
case 0: {
|
2014-12-08 11:09:00 +08:00
|
|
|
return false;
|
2016-09-07 04:57:50 +08:00
|
|
|
} break;
|
|
|
|
}
|
2014-12-08 11:09:00 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
enum i386_eh_regnum {
|
|
|
|
eax = 0,
|
|
|
|
ecx = 1,
|
|
|
|
edx = 2,
|
|
|
|
ebx = 3,
|
|
|
|
ebp = 4,
|
|
|
|
esp = 5,
|
|
|
|
esi = 6,
|
|
|
|
edi = 7,
|
|
|
|
eip = 8 // this is officially the Return Address register number, but close
|
|
|
|
// enough
|
|
|
|
};
|
|
|
|
|
2018-05-01 00:49:04 +08:00
|
|
|
// Convert the compact_unwind_info.h register numbering scheme to
|
|
|
|
// eRegisterKindEHFrame (eh_frame) register numbering scheme.
|
2014-12-08 11:09:00 +08:00
|
|
|
uint32_t translate_to_eh_frame_regnum_i386(uint32_t unwind_regno) {
|
|
|
|
switch (unwind_regno) {
|
|
|
|
case UNWIND_X86_REG_EBX:
|
|
|
|
return i386_eh_regnum::ebx;
|
|
|
|
case UNWIND_X86_REG_ECX:
|
|
|
|
return i386_eh_regnum::ecx;
|
|
|
|
case UNWIND_X86_REG_EDX:
|
|
|
|
return i386_eh_regnum::edx;
|
|
|
|
case UNWIND_X86_REG_EDI:
|
|
|
|
return i386_eh_regnum::edi;
|
|
|
|
case UNWIND_X86_REG_ESI:
|
|
|
|
return i386_eh_regnum::esi;
|
|
|
|
case UNWIND_X86_REG_EBP:
|
|
|
|
return i386_eh_regnum::ebp;
|
|
|
|
default:
|
|
|
|
return LLDB_INVALID_REGNUM;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CompactUnwindInfo::CreateUnwindPlan_i386(Target &target,
|
|
|
|
FunctionInfo &function_info,
|
|
|
|
UnwindPlan &unwind_plan,
|
|
|
|
Address pc_or_function_start) {
|
|
|
|
unwind_plan.SetSourceName("compact unwind info");
|
|
|
|
unwind_plan.SetSourcedFromCompiler(eLazyBoolYes);
|
|
|
|
unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
|
Support Linux signal return trampolines in frame initialization
Summary:
Add __kernel_rt_sigreturn to the list of trap handlers for Linux (it's
used as such on aarch64 at least), and __restore_rt as well (used on
x86_64).
Skip decrement-and-recompute for trap handlers in
InitializeNonZerothFrame, as signal dispatch may point the child frame's
return address to the start of the return trampoline.
Parse the 'S' flag for signal handlers from eh_frame augmentation, and
propagate it to the unwind plan.
Reviewers: labath, jankratochvil, compnerd, jfb, jasonmolenda
Reviewed By: jasonmolenda
Subscribers: clayborg, MaskRay, wuzish, nemanjai, kbarton, jrtc27, atanasyan, jsji, javed.absar, kristof.beyls, lldb-commits
Tags: #lldb
Differential Revision: https://reviews.llvm.org/D63667
llvm-svn: 366580
2019-07-19 22:05:55 +08:00
|
|
|
unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo);
|
2015-08-15 09:21:01 +08:00
|
|
|
unwind_plan.SetRegisterKind(eRegisterKindEHFrame);
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2014-12-08 11:09:00 +08:00
|
|
|
unwind_plan.SetLSDAAddress(function_info.lsda_address);
|
|
|
|
unwind_plan.SetPersonalityFunctionPtr(function_info.personality_ptr_address);
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2014-12-08 11:09:00 +08:00
|
|
|
UnwindPlan::RowSP row(new UnwindPlan::Row);
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2014-12-08 11:09:00 +08:00
|
|
|
const int wordsize = 4;
|
|
|
|
int mode = function_info.encoding & UNWIND_X86_MODE_MASK;
|
|
|
|
switch (mode) {
|
|
|
|
case UNWIND_X86_MODE_EBP_FRAME: {
|
2015-02-23 18:19:16 +08:00
|
|
|
row->GetCFAValue().SetIsRegisterPlusOffset(
|
|
|
|
translate_to_eh_frame_regnum_i386(UNWIND_X86_REG_EBP), 2 * wordsize);
|
2014-12-08 11:09:00 +08:00
|
|
|
row->SetOffset(0);
|
|
|
|
row->SetRegisterLocationToAtCFAPlusOffset(i386_eh_regnum::ebp,
|
|
|
|
wordsize * -2, true);
|
|
|
|
row->SetRegisterLocationToAtCFAPlusOffset(i386_eh_regnum::eip,
|
|
|
|
wordsize * -1, true);
|
|
|
|
row->SetRegisterLocationToIsCFAPlusOffset(i386_eh_regnum::esp, 0, true);
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2014-12-08 11:09:00 +08:00
|
|
|
uint32_t saved_registers_offset =
|
|
|
|
EXTRACT_BITS(function_info.encoding, UNWIND_X86_EBP_FRAME_OFFSET);
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2014-12-08 11:09:00 +08:00
|
|
|
uint32_t saved_registers_locations =
|
|
|
|
EXTRACT_BITS(function_info.encoding, UNWIND_X86_EBP_FRAME_REGISTERS);
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2014-12-08 11:09:00 +08:00
|
|
|
saved_registers_offset += 2;
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2014-12-08 11:09:00 +08:00
|
|
|
for (int i = 0; i < 5; i++) {
|
|
|
|
uint32_t regnum = saved_registers_locations & 0x7;
|
|
|
|
switch (regnum) {
|
|
|
|
case UNWIND_X86_REG_NONE:
|
|
|
|
break;
|
|
|
|
case UNWIND_X86_REG_EBX:
|
|
|
|
case UNWIND_X86_REG_ECX:
|
|
|
|
case UNWIND_X86_REG_EDX:
|
|
|
|
case UNWIND_X86_REG_EDI:
|
|
|
|
case UNWIND_X86_REG_ESI:
|
2014-12-22 19:02:02 +08:00
|
|
|
row->SetRegisterLocationToAtCFAPlusOffset(
|
2015-01-23 09:02:32 +08:00
|
|
|
translate_to_eh_frame_regnum_i386(regnum),
|
|
|
|
wordsize * -saved_registers_offset, true);
|
2016-09-07 04:57:50 +08:00
|
|
|
break;
|
|
|
|
}
|
2014-12-08 11:09:00 +08:00
|
|
|
saved_registers_offset--;
|
|
|
|
saved_registers_locations >>= 3;
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2014-12-22 19:02:02 +08:00
|
|
|
unwind_plan.AppendRow(row);
|
2014-12-08 11:09:00 +08:00
|
|
|
return true;
|
2016-09-07 04:57:50 +08:00
|
|
|
} break;
|
|
|
|
|
2014-12-08 11:09:00 +08:00
|
|
|
case UNWIND_X86_MODE_STACK_IND:
|
|
|
|
case UNWIND_X86_MODE_STACK_IMMD: {
|
2014-12-22 19:02:02 +08:00
|
|
|
uint32_t stack_size =
|
|
|
|
EXTRACT_BITS(function_info.encoding, UNWIND_X86_FRAMELESS_STACK_SIZE);
|
|
|
|
uint32_t register_count = EXTRACT_BITS(
|
|
|
|
function_info.encoding, UNWIND_X86_FRAMELESS_STACK_REG_COUNT);
|
|
|
|
uint32_t permutation = EXTRACT_BITS(
|
|
|
|
function_info.encoding, UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION);
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2014-12-22 19:02:02 +08:00
|
|
|
if (mode == UNWIND_X86_MODE_STACK_IND &&
|
|
|
|
function_info.valid_range_offset_start != 0) {
|
|
|
|
uint32_t stack_adjust = EXTRACT_BITS(function_info.encoding,
|
|
|
|
UNWIND_X86_FRAMELESS_STACK_ADJUST);
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2014-12-22 19:02:02 +08:00
|
|
|
// offset into the function instructions; 0 == beginning of first
|
|
|
|
// instruction
|
|
|
|
uint32_t offset_to_subl_insn =
|
|
|
|
EXTRACT_BITS(function_info.encoding, UNWIND_X86_FRAMELESS_STACK_SIZE);
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2014-12-22 19:02:02 +08:00
|
|
|
SectionList *sl = m_objfile.GetSectionList();
|
2016-09-07 04:57:50 +08:00
|
|
|
if (sl) {
|
2014-12-22 19:02:02 +08:00
|
|
|
ProcessSP process_sp = target.GetProcessSP();
|
|
|
|
if (process_sp) {
|
|
|
|
Address subl_payload_addr(function_info.valid_range_offset_start, sl);
|
|
|
|
subl_payload_addr.Slide(offset_to_subl_insn);
|
2017-05-12 12:51:55 +08:00
|
|
|
Status error;
|
2014-12-22 19:02:02 +08:00
|
|
|
uint64_t large_stack_size = process_sp->ReadUnsignedIntegerFromMemory(
|
|
|
|
subl_payload_addr.GetLoadAddress(&target), 4, 0, error);
|
|
|
|
if (large_stack_size != 0 && error.Success()) {
|
|
|
|
// Got the large stack frame size correctly - use it
|
|
|
|
stack_size = large_stack_size + (stack_adjust * wordsize);
|
2016-09-07 04:57:50 +08:00
|
|
|
} else {
|
2014-12-22 19:02:02 +08:00
|
|
|
return false;
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
} else {
|
2014-12-22 19:02:02 +08:00
|
|
|
return false;
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
} else {
|
2014-12-22 19:02:02 +08:00
|
|
|
return false;
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
}
|
2014-12-08 11:09:00 +08:00
|
|
|
|
2014-12-22 19:02:02 +08:00
|
|
|
int32_t offset =
|
|
|
|
mode == UNWIND_X86_MODE_STACK_IND ? stack_size : stack_size * wordsize;
|
|
|
|
row->GetCFAValue().SetIsRegisterPlusOffset(i386_eh_regnum::esp, offset);
|
|
|
|
row->SetOffset(0);
|
|
|
|
row->SetRegisterLocationToAtCFAPlusOffset(i386_eh_regnum::eip,
|
|
|
|
wordsize * -1, true);
|
|
|
|
row->SetRegisterLocationToIsCFAPlusOffset(i386_eh_regnum::esp, 0, true);
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2014-12-22 19:02:02 +08:00
|
|
|
if (register_count > 0) {
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2018-05-01 00:49:04 +08:00
|
|
|
// We need to include (up to) 6 registers in 10 bits. That would be 18
|
|
|
|
// bits if we just used 3 bits per reg to indicate the order they're
|
|
|
|
// saved on the stack.
|
2016-09-07 04:57:50 +08:00
|
|
|
//
|
2014-12-22 19:02:02 +08:00
|
|
|
// This is done with Lehmer code permutation, e.g. see
|
2018-05-01 00:49:04 +08:00
|
|
|
// http://stackoverflow.com/questions/1506078/fast-permutation-number-
|
|
|
|
// permutation-mapping-algorithms
|
2014-12-22 19:02:02 +08:00
|
|
|
int permunreg[6] = {0, 0, 0, 0, 0, 0};
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2018-05-01 00:49:04 +08:00
|
|
|
// This decodes the variable-base number in the 10 bits and gives us the
|
|
|
|
// Lehmer code sequence which can then be decoded.
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2015-02-23 18:19:16 +08:00
|
|
|
switch (register_count) {
|
|
|
|
case 6:
|
|
|
|
permunreg[0] = permutation / 120; // 120 == 5!
|
2014-12-22 19:02:02 +08:00
|
|
|
permutation -= (permunreg[0] * 120);
|
|
|
|
permunreg[1] = permutation / 24; // 24 == 4!
|
|
|
|
permutation -= (permunreg[1] * 24);
|
|
|
|
permunreg[2] = permutation / 6; // 6 == 3!
|
|
|
|
permutation -= (permunreg[2] * 6);
|
|
|
|
permunreg[3] = permutation / 2; // 2 == 2!
|
2015-05-05 10:05:53 +08:00
|
|
|
permutation -= (permunreg[3] * 2);
|
2014-12-22 19:02:02 +08:00
|
|
|
permunreg[4] = permutation; // 1 == 1!
|
|
|
|
permunreg[5] = 0;
|
2016-09-07 04:57:50 +08:00
|
|
|
break;
|
2014-12-22 19:02:02 +08:00
|
|
|
case 5:
|
|
|
|
permunreg[0] = permutation / 120;
|
|
|
|
permutation -= (permunreg[0] * 120);
|
|
|
|
permunreg[1] = permutation / 24;
|
|
|
|
permutation -= (permunreg[1] * 24);
|
|
|
|
permunreg[2] = permutation / 6;
|
|
|
|
permutation -= (permunreg[2] * 6);
|
|
|
|
permunreg[3] = permutation / 2;
|
|
|
|
permutation -= (permunreg[3] * 2);
|
|
|
|
permunreg[4] = permutation;
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
permunreg[0] = permutation / 60;
|
|
|
|
permutation -= (permunreg[0] * 60);
|
|
|
|
permunreg[1] = permutation / 12;
|
|
|
|
permutation -= (permunreg[1] * 12);
|
|
|
|
permunreg[2] = permutation / 3;
|
|
|
|
permutation -= (permunreg[2] * 3);
|
|
|
|
permunreg[3] = permutation;
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
permunreg[0] = permutation / 20;
|
|
|
|
permutation -= (permunreg[0] * 20);
|
|
|
|
permunreg[1] = permutation / 4;
|
|
|
|
permutation -= (permunreg[1] * 4);
|
|
|
|
permunreg[2] = permutation;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
permunreg[0] = permutation / 5;
|
|
|
|
permutation -= (permunreg[0] * 5);
|
|
|
|
permunreg[1] = permutation;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
permunreg[0] = permutation;
|
|
|
|
break;
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
|
2018-05-01 00:49:04 +08:00
|
|
|
// Decode the Lehmer code for this permutation of the registers v.
|
|
|
|
// http://en.wikipedia.org/wiki/Lehmer_code
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2014-12-22 19:02:02 +08:00
|
|
|
int registers[6] = {UNWIND_X86_REG_NONE, UNWIND_X86_REG_NONE,
|
2015-05-05 10:05:53 +08:00
|
|
|
UNWIND_X86_REG_NONE, UNWIND_X86_REG_NONE,
|
2014-12-22 19:02:02 +08:00
|
|
|
UNWIND_X86_REG_NONE, UNWIND_X86_REG_NONE};
|
|
|
|
bool used[7] = {false, false, false, false, false, false, false};
|
|
|
|
for (uint32_t i = 0; i < register_count; i++) {
|
|
|
|
int renum = 0;
|
|
|
|
for (int j = 1; j < 7; j++) {
|
2018-12-15 08:15:33 +08:00
|
|
|
if (!used[j]) {
|
2015-01-23 09:02:32 +08:00
|
|
|
if (renum == permunreg[i]) {
|
|
|
|
registers[i] = j;
|
|
|
|
used[j] = true;
|
2014-12-22 19:02:02 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
renum++;
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2014-12-22 19:02:02 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2014-12-22 19:02:02 +08:00
|
|
|
|
2014-12-08 11:09:00 +08:00
|
|
|
uint32_t saved_registers_offset = 1;
|
2015-01-23 09:02:32 +08:00
|
|
|
saved_registers_offset++;
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2014-12-22 19:02:02 +08:00
|
|
|
for (int i = (sizeof(registers) / sizeof(int)) - 1; i >= 0; i--) {
|
|
|
|
switch (registers[i]) {
|
2014-12-08 11:09:00 +08:00
|
|
|
case UNWIND_X86_REG_NONE:
|
|
|
|
break;
|
2014-12-22 19:02:02 +08:00
|
|
|
case UNWIND_X86_REG_EBX:
|
|
|
|
case UNWIND_X86_REG_ECX:
|
|
|
|
case UNWIND_X86_REG_EDX:
|
|
|
|
case UNWIND_X86_REG_EDI:
|
|
|
|
case UNWIND_X86_REG_ESI:
|
|
|
|
case UNWIND_X86_REG_EBP:
|
2014-12-08 11:09:00 +08:00
|
|
|
row->SetRegisterLocationToAtCFAPlusOffset(
|
2015-01-23 09:02:32 +08:00
|
|
|
translate_to_eh_frame_regnum_i386(registers[i]),
|
2014-12-08 11:09:00 +08:00
|
|
|
wordsize * -saved_registers_offset, true);
|
2015-01-23 09:02:32 +08:00
|
|
|
saved_registers_offset++;
|
2016-09-07 04:57:50 +08:00
|
|
|
break;
|
2014-12-08 11:09:00 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2014-12-08 11:09:00 +08:00
|
|
|
}
|
2016-05-25 12:20:28 +08:00
|
|
|
|
2014-12-22 19:02:02 +08:00
|
|
|
unwind_plan.AppendRow(row);
|
2014-12-08 11:09:00 +08:00
|
|
|
return true;
|
2016-09-07 04:57:50 +08:00
|
|
|
} break;
|
2016-05-25 12:20:28 +08:00
|
|
|
|
2014-12-08 11:09:00 +08:00
|
|
|
case UNWIND_X86_MODE_DWARF: {
|
|
|
|
return false;
|
2016-09-07 04:57:50 +08:00
|
|
|
} break;
|
|
|
|
}
|
2014-12-08 11:09:00 +08:00
|
|
|
return false;
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2016-05-25 12:20:28 +08:00
|
|
|
|
|
|
|
// DWARF register numbers from "DWARF for the ARM 64-bit Architecture (AArch64)"
|
|
|
|
// doc by ARM
|
|
|
|
|
|
|
|
enum arm64_eh_regnum {
|
|
|
|
x19 = 19,
|
|
|
|
x20 = 20,
|
|
|
|
x21 = 21,
|
|
|
|
x22 = 22,
|
|
|
|
x23 = 23,
|
|
|
|
x24 = 24,
|
|
|
|
x25 = 25,
|
|
|
|
x26 = 26,
|
|
|
|
x27 = 27,
|
|
|
|
x28 = 28,
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2016-05-25 12:20:28 +08:00
|
|
|
fp = 29,
|
|
|
|
ra = 30,
|
|
|
|
sp = 31,
|
|
|
|
pc = 32,
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2016-05-25 12:20:28 +08:00
|
|
|
// Compact unwind encodes d8-d15 but we don't have eh_frame / dwarf reg #'s
|
2018-05-01 00:49:04 +08:00
|
|
|
// for the 64-bit fp regs. Normally in DWARF it's context sensitive - so it
|
|
|
|
// knows it is fetching a 32- or 64-bit quantity from reg v8 to indicate s0
|
|
|
|
// or d0 - but the unwinder is operating at a lower level and we'd try to
|
|
|
|
// fetch 128 bits if we were told that v8 were stored on the stack...
|
2016-06-07 10:19:54 +08:00
|
|
|
v8 = 72,
|
|
|
|
v9 = 73,
|
|
|
|
v10 = 74,
|
|
|
|
v11 = 75,
|
|
|
|
v12 = 76,
|
|
|
|
v13 = 77,
|
|
|
|
v14 = 78,
|
|
|
|
v15 = 79,
|
2016-05-25 12:20:28 +08:00
|
|
|
};
|
|
|
|
|
2016-06-07 10:19:54 +08:00
|
|
|
enum arm_eh_regnum {
|
|
|
|
arm_r0 = 0,
|
|
|
|
arm_r1 = 1,
|
|
|
|
arm_r2 = 2,
|
|
|
|
arm_r3 = 3,
|
|
|
|
arm_r4 = 4,
|
|
|
|
arm_r5 = 5,
|
|
|
|
arm_r6 = 6,
|
|
|
|
arm_r7 = 7,
|
|
|
|
arm_r8 = 8,
|
|
|
|
arm_r9 = 9,
|
|
|
|
arm_r10 = 10,
|
|
|
|
arm_r11 = 11,
|
|
|
|
arm_r12 = 12,
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2016-06-07 10:19:54 +08:00
|
|
|
arm_sp = 13,
|
|
|
|
arm_lr = 14,
|
|
|
|
arm_pc = 15,
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2016-06-07 10:19:54 +08:00
|
|
|
arm_d0 = 256,
|
|
|
|
arm_d1 = 257,
|
|
|
|
arm_d2 = 258,
|
|
|
|
arm_d3 = 259,
|
|
|
|
arm_d4 = 260,
|
|
|
|
arm_d5 = 261,
|
|
|
|
arm_d6 = 262,
|
|
|
|
arm_d7 = 263,
|
|
|
|
arm_d8 = 264,
|
|
|
|
arm_d9 = 265,
|
|
|
|
arm_d10 = 266,
|
|
|
|
arm_d11 = 267,
|
|
|
|
arm_d12 = 268,
|
|
|
|
arm_d13 = 269,
|
|
|
|
arm_d14 = 270,
|
|
|
|
};
|
|
|
|
|
2016-05-25 12:20:28 +08:00
|
|
|
bool CompactUnwindInfo::CreateUnwindPlan_arm64(Target &target,
|
|
|
|
FunctionInfo &function_info,
|
|
|
|
UnwindPlan &unwind_plan,
|
|
|
|
Address pc_or_function_start) {
|
|
|
|
unwind_plan.SetSourceName("compact unwind info");
|
|
|
|
unwind_plan.SetSourcedFromCompiler(eLazyBoolYes);
|
|
|
|
unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
|
Support Linux signal return trampolines in frame initialization
Summary:
Add __kernel_rt_sigreturn to the list of trap handlers for Linux (it's
used as such on aarch64 at least), and __restore_rt as well (used on
x86_64).
Skip decrement-and-recompute for trap handlers in
InitializeNonZerothFrame, as signal dispatch may point the child frame's
return address to the start of the return trampoline.
Parse the 'S' flag for signal handlers from eh_frame augmentation, and
propagate it to the unwind plan.
Reviewers: labath, jankratochvil, compnerd, jfb, jasonmolenda
Reviewed By: jasonmolenda
Subscribers: clayborg, MaskRay, wuzish, nemanjai, kbarton, jrtc27, atanasyan, jsji, javed.absar, kristof.beyls, lldb-commits
Tags: #lldb
Differential Revision: https://reviews.llvm.org/D63667
llvm-svn: 366580
2019-07-19 22:05:55 +08:00
|
|
|
unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo);
|
2016-05-25 12:20:28 +08:00
|
|
|
unwind_plan.SetRegisterKind(eRegisterKindEHFrame);
|
2016-06-07 10:19:54 +08:00
|
|
|
|
2016-05-25 12:20:28 +08:00
|
|
|
unwind_plan.SetLSDAAddress(function_info.lsda_address);
|
|
|
|
unwind_plan.SetPersonalityFunctionPtr(function_info.personality_ptr_address);
|
2016-06-07 10:19:54 +08:00
|
|
|
|
2016-05-25 12:20:28 +08:00
|
|
|
UnwindPlan::RowSP row(new UnwindPlan::Row);
|
|
|
|
|
|
|
|
const int wordsize = 8;
|
|
|
|
int mode = function_info.encoding & UNWIND_ARM64_MODE_MASK;
|
2016-06-07 10:19:54 +08:00
|
|
|
|
2016-05-25 12:20:28 +08:00
|
|
|
if (mode == UNWIND_ARM64_MODE_DWARF)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (mode == UNWIND_ARM64_MODE_FRAMELESS) {
|
|
|
|
row->SetOffset(0);
|
|
|
|
|
|
|
|
uint32_t stack_size =
|
|
|
|
(EXTRACT_BITS(function_info.encoding,
|
|
|
|
UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK)) *
|
|
|
|
16;
|
|
|
|
|
|
|
|
// Our previous Call Frame Address is the stack pointer plus the stack size
|
|
|
|
row->GetCFAValue().SetIsRegisterPlusOffset(arm64_eh_regnum::sp, stack_size);
|
|
|
|
|
|
|
|
// Our previous PC is in the LR
|
|
|
|
row->SetRegisterLocationToRegister(arm64_eh_regnum::pc, arm64_eh_regnum::ra,
|
|
|
|
true);
|
|
|
|
|
|
|
|
unwind_plan.AppendRow(row);
|
|
|
|
return true;
|
|
|
|
}
|
2016-06-07 10:19:54 +08:00
|
|
|
|
|
|
|
// Should not be possible
|
|
|
|
if (mode != UNWIND_ARM64_MODE_FRAME)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// mode == UNWIND_ARM64_MODE_FRAME
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2016-05-25 12:20:28 +08:00
|
|
|
row->GetCFAValue().SetIsRegisterPlusOffset(arm64_eh_regnum::fp, 2 * wordsize);
|
|
|
|
row->SetOffset(0);
|
2016-06-07 10:19:54 +08:00
|
|
|
row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::fp, wordsize * -2,
|
2016-09-07 04:57:50 +08:00
|
|
|
true);
|
2016-05-25 12:20:28 +08:00
|
|
|
row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::pc, wordsize * -1,
|
2016-09-07 04:57:50 +08:00
|
|
|
true);
|
2016-05-25 12:20:28 +08:00
|
|
|
row->SetRegisterLocationToIsCFAPlusOffset(arm64_eh_regnum::sp, 0, true);
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2016-06-07 10:19:54 +08:00
|
|
|
int reg_pairs_saved_count = 1;
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2016-05-25 12:20:28 +08:00
|
|
|
uint32_t saved_register_bits = function_info.encoding & 0xfff;
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2016-06-07 10:19:54 +08:00
|
|
|
if (saved_register_bits & UNWIND_ARM64_FRAME_X19_X20_PAIR) {
|
2016-05-25 12:20:28 +08:00
|
|
|
int cfa_offset = reg_pairs_saved_count * -2 * wordsize;
|
|
|
|
cfa_offset -= wordsize;
|
|
|
|
row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x19, cfa_offset,
|
2016-09-07 04:57:50 +08:00
|
|
|
true);
|
2016-06-07 10:19:54 +08:00
|
|
|
cfa_offset -= wordsize;
|
2016-05-25 12:20:28 +08:00
|
|
|
row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x20, cfa_offset,
|
2016-06-07 10:19:54 +08:00
|
|
|
true);
|
2016-05-25 12:20:28 +08:00
|
|
|
reg_pairs_saved_count++;
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
|
2016-06-07 10:19:54 +08:00
|
|
|
if (saved_register_bits & UNWIND_ARM64_FRAME_X21_X22_PAIR) {
|
|
|
|
int cfa_offset = reg_pairs_saved_count * -2 * wordsize;
|
2016-05-25 12:20:28 +08:00
|
|
|
cfa_offset -= wordsize;
|
|
|
|
row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x21, cfa_offset,
|
2016-09-07 04:57:50 +08:00
|
|
|
true);
|
2016-05-25 12:20:28 +08:00
|
|
|
cfa_offset -= wordsize;
|
2016-06-07 10:19:54 +08:00
|
|
|
row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x22, cfa_offset,
|
2016-09-07 04:57:50 +08:00
|
|
|
true);
|
2016-05-25 12:20:28 +08:00
|
|
|
reg_pairs_saved_count++;
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
|
2016-05-25 12:20:28 +08:00
|
|
|
if (saved_register_bits & UNWIND_ARM64_FRAME_X23_X24_PAIR) {
|
|
|
|
int cfa_offset = reg_pairs_saved_count * -2 * wordsize;
|
|
|
|
cfa_offset -= wordsize;
|
|
|
|
row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x23, cfa_offset,
|
2016-09-07 04:57:50 +08:00
|
|
|
true);
|
2016-05-25 12:20:28 +08:00
|
|
|
cfa_offset -= wordsize;
|
|
|
|
row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x24, cfa_offset,
|
2016-09-07 04:57:50 +08:00
|
|
|
true);
|
2016-05-25 12:20:28 +08:00
|
|
|
reg_pairs_saved_count++;
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
|
2016-05-25 12:20:28 +08:00
|
|
|
if (saved_register_bits & UNWIND_ARM64_FRAME_X25_X26_PAIR) {
|
|
|
|
int cfa_offset = reg_pairs_saved_count * -2 * wordsize;
|
|
|
|
cfa_offset -= wordsize;
|
|
|
|
row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x25, cfa_offset,
|
2016-09-07 04:57:50 +08:00
|
|
|
true);
|
2016-05-25 12:20:28 +08:00
|
|
|
cfa_offset -= wordsize;
|
|
|
|
row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x26, cfa_offset,
|
2016-09-07 04:57:50 +08:00
|
|
|
true);
|
2016-05-25 12:20:28 +08:00
|
|
|
reg_pairs_saved_count++;
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
|
2016-05-25 12:20:28 +08:00
|
|
|
if (saved_register_bits & UNWIND_ARM64_FRAME_X27_X28_PAIR) {
|
|
|
|
int cfa_offset = reg_pairs_saved_count * -2 * wordsize;
|
|
|
|
cfa_offset -= wordsize;
|
|
|
|
row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x27, cfa_offset,
|
2016-09-07 04:57:50 +08:00
|
|
|
true);
|
2016-05-25 12:20:28 +08:00
|
|
|
cfa_offset -= wordsize;
|
|
|
|
row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x28, cfa_offset,
|
2016-09-07 04:57:50 +08:00
|
|
|
true);
|
2016-05-25 12:20:28 +08:00
|
|
|
reg_pairs_saved_count++;
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
|
2016-06-07 10:19:54 +08:00
|
|
|
// If we use the v8-v15 regnums here, the unwinder will try to grab 128 bits
|
2016-05-25 12:20:28 +08:00
|
|
|
// off the stack;
|
|
|
|
// not sure if we have a good way to represent the 64-bitness of these saves.
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2016-05-25 12:20:28 +08:00
|
|
|
if (saved_register_bits & UNWIND_ARM64_FRAME_D8_D9_PAIR) {
|
|
|
|
reg_pairs_saved_count++;
|
2016-06-07 10:19:54 +08:00
|
|
|
}
|
2016-05-25 12:20:28 +08:00
|
|
|
if (saved_register_bits & UNWIND_ARM64_FRAME_D10_D11_PAIR) {
|
|
|
|
reg_pairs_saved_count++;
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2016-05-25 12:20:28 +08:00
|
|
|
if (saved_register_bits & UNWIND_ARM64_FRAME_D12_D13_PAIR) {
|
|
|
|
reg_pairs_saved_count++;
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2016-05-25 12:20:28 +08:00
|
|
|
if (saved_register_bits & UNWIND_ARM64_FRAME_D14_D15_PAIR) {
|
|
|
|
reg_pairs_saved_count++;
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
|
2014-12-22 19:02:02 +08:00
|
|
|
unwind_plan.AppendRow(row);
|
2016-05-25 12:20:28 +08:00
|
|
|
return true;
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2016-06-07 10:19:54 +08:00
|
|
|
|
|
|
|
bool CompactUnwindInfo::CreateUnwindPlan_armv7(Target &target,
|
|
|
|
FunctionInfo &function_info,
|
|
|
|
UnwindPlan &unwind_plan,
|
|
|
|
Address pc_or_function_start) {
|
|
|
|
unwind_plan.SetSourceName("compact unwind info");
|
|
|
|
unwind_plan.SetSourcedFromCompiler(eLazyBoolYes);
|
|
|
|
unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
|
Support Linux signal return trampolines in frame initialization
Summary:
Add __kernel_rt_sigreturn to the list of trap handlers for Linux (it's
used as such on aarch64 at least), and __restore_rt as well (used on
x86_64).
Skip decrement-and-recompute for trap handlers in
InitializeNonZerothFrame, as signal dispatch may point the child frame's
return address to the start of the return trampoline.
Parse the 'S' flag for signal handlers from eh_frame augmentation, and
propagate it to the unwind plan.
Reviewers: labath, jankratochvil, compnerd, jfb, jasonmolenda
Reviewed By: jasonmolenda
Subscribers: clayborg, MaskRay, wuzish, nemanjai, kbarton, jrtc27, atanasyan, jsji, javed.absar, kristof.beyls, lldb-commits
Tags: #lldb
Differential Revision: https://reviews.llvm.org/D63667
llvm-svn: 366580
2019-07-19 22:05:55 +08:00
|
|
|
unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo);
|
2016-06-07 10:19:54 +08:00
|
|
|
unwind_plan.SetRegisterKind(eRegisterKindEHFrame);
|
|
|
|
|
|
|
|
unwind_plan.SetLSDAAddress(function_info.lsda_address);
|
|
|
|
unwind_plan.SetPersonalityFunctionPtr(function_info.personality_ptr_address);
|
|
|
|
|
|
|
|
UnwindPlan::RowSP row(new UnwindPlan::Row);
|
|
|
|
|
|
|
|
const int wordsize = 4;
|
|
|
|
int mode = function_info.encoding & UNWIND_ARM_MODE_MASK;
|
|
|
|
|
|
|
|
if (mode == UNWIND_ARM_MODE_DWARF)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
uint32_t stack_adjust = (EXTRACT_BITS(function_info.encoding,
|
|
|
|
UNWIND_ARM_FRAME_STACK_ADJUST_MASK)) *
|
2016-05-25 12:20:28 +08:00
|
|
|
wordsize;
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2016-06-07 10:19:54 +08:00
|
|
|
row->GetCFAValue().SetIsRegisterPlusOffset(arm_r7,
|
|
|
|
(2 * wordsize) + stack_adjust);
|
|
|
|
row->SetOffset(0);
|
2016-05-25 12:20:28 +08:00
|
|
|
row->SetRegisterLocationToAtCFAPlusOffset(
|
2016-06-07 10:19:54 +08:00
|
|
|
arm_r7, (wordsize * -2) - stack_adjust, true);
|
2016-05-25 12:20:28 +08:00
|
|
|
row->SetRegisterLocationToAtCFAPlusOffset(
|
2016-06-07 10:19:54 +08:00
|
|
|
arm_pc, (wordsize * -1) - stack_adjust, true);
|
|
|
|
row->SetRegisterLocationToIsCFAPlusOffset(arm_sp, 0, true);
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2016-06-07 10:19:54 +08:00
|
|
|
int cfa_offset = -stack_adjust - (2 * wordsize);
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2016-06-07 10:19:54 +08:00
|
|
|
uint32_t saved_register_bits = function_info.encoding & 0xff;
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2016-06-07 10:19:54 +08:00
|
|
|
if (saved_register_bits & UNWIND_ARM_FRAME_FIRST_PUSH_R6) {
|
|
|
|
cfa_offset -= wordsize;
|
|
|
|
row->SetRegisterLocationToAtCFAPlusOffset(arm_r6, cfa_offset, true);
|
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2016-06-07 10:19:54 +08:00
|
|
|
if (saved_register_bits & UNWIND_ARM_FRAME_FIRST_PUSH_R5) {
|
|
|
|
cfa_offset -= wordsize;
|
|
|
|
row->SetRegisterLocationToAtCFAPlusOffset(arm_r5, cfa_offset, true);
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
|
2016-06-07 10:19:54 +08:00
|
|
|
if (saved_register_bits & UNWIND_ARM_FRAME_FIRST_PUSH_R4) {
|
|
|
|
cfa_offset -= wordsize;
|
|
|
|
row->SetRegisterLocationToAtCFAPlusOffset(arm_r4, cfa_offset, true);
|
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2016-06-07 10:19:54 +08:00
|
|
|
if (saved_register_bits & UNWIND_ARM_FRAME_SECOND_PUSH_R12) {
|
|
|
|
cfa_offset -= wordsize;
|
|
|
|
row->SetRegisterLocationToAtCFAPlusOffset(arm_r12, cfa_offset, true);
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
|
2016-06-07 10:19:54 +08:00
|
|
|
if (saved_register_bits & UNWIND_ARM_FRAME_SECOND_PUSH_R11) {
|
|
|
|
cfa_offset -= wordsize;
|
|
|
|
row->SetRegisterLocationToAtCFAPlusOffset(arm_r11, cfa_offset, true);
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
|
2016-06-07 10:19:54 +08:00
|
|
|
if (saved_register_bits & UNWIND_ARM_FRAME_SECOND_PUSH_R10) {
|
|
|
|
cfa_offset -= wordsize;
|
|
|
|
row->SetRegisterLocationToAtCFAPlusOffset(arm_r10, cfa_offset, true);
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
|
2016-06-07 10:19:54 +08:00
|
|
|
if (saved_register_bits & UNWIND_ARM_FRAME_SECOND_PUSH_R9) {
|
|
|
|
cfa_offset -= wordsize;
|
|
|
|
row->SetRegisterLocationToAtCFAPlusOffset(arm_r9, cfa_offset, true);
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
|
2016-06-07 10:19:54 +08:00
|
|
|
if (saved_register_bits & UNWIND_ARM_FRAME_SECOND_PUSH_R8) {
|
|
|
|
cfa_offset -= wordsize;
|
|
|
|
row->SetRegisterLocationToAtCFAPlusOffset(arm_r8, cfa_offset, true);
|
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2016-06-07 10:19:54 +08:00
|
|
|
if (mode == UNWIND_ARM_MODE_FRAME_D) {
|
|
|
|
uint32_t d_reg_bits =
|
|
|
|
EXTRACT_BITS(function_info.encoding, UNWIND_ARM_FRAME_D_REG_COUNT_MASK);
|
|
|
|
switch (d_reg_bits) {
|
|
|
|
case 0:
|
|
|
|
// vpush {d8}
|
|
|
|
cfa_offset -= 8;
|
|
|
|
row->SetRegisterLocationToAtCFAPlusOffset(arm_d8, cfa_offset, true);
|
2016-09-07 04:57:50 +08:00
|
|
|
break;
|
|
|
|
case 1:
|
2016-06-07 10:19:54 +08:00
|
|
|
// vpush {d10}
|
|
|
|
// vpush {d8}
|
|
|
|
cfa_offset -= 8;
|
|
|
|
row->SetRegisterLocationToAtCFAPlusOffset(arm_d10, cfa_offset, true);
|
|
|
|
cfa_offset -= 8;
|
|
|
|
row->SetRegisterLocationToAtCFAPlusOffset(arm_d8, cfa_offset, true);
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
// vpush {d12}
|
|
|
|
// vpush {d10}
|
|
|
|
// vpush {d8}
|
|
|
|
cfa_offset -= 8;
|
|
|
|
row->SetRegisterLocationToAtCFAPlusOffset(arm_d12, cfa_offset, true);
|
|
|
|
cfa_offset -= 8;
|
|
|
|
row->SetRegisterLocationToAtCFAPlusOffset(arm_d10, cfa_offset, true);
|
|
|
|
cfa_offset -= 8;
|
|
|
|
row->SetRegisterLocationToAtCFAPlusOffset(arm_d8, cfa_offset, true);
|
2016-09-07 04:57:50 +08:00
|
|
|
break;
|
|
|
|
case 3:
|
2016-06-07 10:19:54 +08:00
|
|
|
// vpush {d14}
|
|
|
|
// vpush {d12}
|
|
|
|
// vpush {d10}
|
|
|
|
// vpush {d8}
|
|
|
|
cfa_offset -= 8;
|
|
|
|
row->SetRegisterLocationToAtCFAPlusOffset(arm_d14, cfa_offset, true);
|
|
|
|
cfa_offset -= 8;
|
|
|
|
row->SetRegisterLocationToAtCFAPlusOffset(arm_d12, cfa_offset, true);
|
|
|
|
cfa_offset -= 8;
|
|
|
|
row->SetRegisterLocationToAtCFAPlusOffset(arm_d10, cfa_offset, true);
|
|
|
|
cfa_offset -= 8;
|
|
|
|
row->SetRegisterLocationToAtCFAPlusOffset(arm_d8, cfa_offset, true);
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
// vpush {d14}
|
|
|
|
// vpush {d12}
|
|
|
|
// sp = (sp - 24) & (-16);
|
|
|
|
// vst {d8, d9, d10}
|
|
|
|
cfa_offset -= 8;
|
|
|
|
row->SetRegisterLocationToAtCFAPlusOffset(arm_d14, cfa_offset, true);
|
|
|
|
cfa_offset -= 8;
|
|
|
|
row->SetRegisterLocationToAtCFAPlusOffset(arm_d12, cfa_offset, true);
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2016-06-07 10:19:54 +08:00
|
|
|
// FIXME we don't have a way to represent reg saves at an specific
|
|
|
|
// alignment short of
|
|
|
|
// coming up with some DWARF location description.
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2016-06-07 10:19:54 +08:00
|
|
|
break;
|
2016-09-07 04:57:50 +08:00
|
|
|
case 5:
|
2016-06-07 10:19:54 +08:00
|
|
|
// vpush {d14}
|
|
|
|
// sp = (sp - 40) & (-16);
|
|
|
|
// vst {d8, d9, d10, d11}
|
|
|
|
// vst {d12}
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2016-06-07 10:19:54 +08:00
|
|
|
cfa_offset -= 8;
|
|
|
|
row->SetRegisterLocationToAtCFAPlusOffset(arm_d14, cfa_offset, true);
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2016-06-07 10:19:54 +08:00
|
|
|
// FIXME we don't have a way to represent reg saves at an specific
|
|
|
|
// alignment short of
|
|
|
|
// coming up with some DWARF location description.
|
2016-09-07 04:57:50 +08:00
|
|
|
|
|
|
|
break;
|
2016-06-07 10:19:54 +08:00
|
|
|
case 6:
|
|
|
|
// sp = (sp - 56) & (-16);
|
|
|
|
// vst {d8, d9, d10, d11}
|
|
|
|
// vst {d12, d13, d14}
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2016-06-07 10:19:54 +08:00
|
|
|
// FIXME we don't have a way to represent reg saves at an specific
|
|
|
|
// alignment short of
|
|
|
|
// coming up with some DWARF location description.
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2016-06-07 10:19:54 +08:00
|
|
|
break;
|
|
|
|
case 7:
|
|
|
|
// sp = (sp - 64) & (-16);
|
|
|
|
// vst {d8, d9, d10, d11}
|
|
|
|
// vst {d12, d13, d14, d15}
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2016-06-07 10:19:54 +08:00
|
|
|
// FIXME we don't have a way to represent reg saves at an specific
|
|
|
|
// alignment short of
|
|
|
|
// coming up with some DWARF location description.
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2016-06-07 10:19:54 +08:00
|
|
|
break;
|
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2016-06-07 10:19:54 +08:00
|
|
|
|
|
|
|
unwind_plan.AppendRow(row);
|
|
|
|
return true;
|
|
|
|
}
|