[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
|
|
|
//===-- UnwindPlan.cpp ----------------------------------------------------===//
|
2010-09-10 15:49:16 +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
|
2010-09-10 15:49:16 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "lldb/Symbol/UnwindPlan.h"
|
2011-04-27 07:48:45 +08:00
|
|
|
|
2019-04-23 17:16:51 +08:00
|
|
|
#include "lldb/Expression/DWARFExpression.h"
|
2010-09-15 07:36:40 +08:00
|
|
|
#include "lldb/Target/Process.h"
|
2010-09-10 15:49:16 +08:00
|
|
|
#include "lldb/Target/RegisterContext.h"
|
2019-04-23 17:16:51 +08:00
|
|
|
#include "lldb/Target/Target.h"
|
2010-09-15 07:36:40 +08:00
|
|
|
#include "lldb/Target/Thread.h"
|
2017-02-03 05:39:50 +08:00
|
|
|
#include "lldb/Utility/ConstString.h"
|
2017-03-04 04:56:28 +08:00
|
|
|
#include "lldb/Utility/Log.h"
|
2020-05-25 21:59:48 +08:00
|
|
|
#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
|
2010-09-10 15:49:16 +08:00
|
|
|
|
|
|
|
using namespace lldb;
|
|
|
|
using namespace lldb_private;
|
|
|
|
|
|
|
|
bool UnwindPlan::Row::RegisterLocation::
|
|
|
|
operator==(const UnwindPlan::Row::RegisterLocation &rhs) const {
|
2011-05-12 02:39:18 +08:00
|
|
|
if (m_type == rhs.m_type) {
|
|
|
|
switch (m_type) {
|
|
|
|
case unspecified:
|
|
|
|
case undefined:
|
|
|
|
case same:
|
|
|
|
return true;
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2011-05-12 02:39:18 +08:00
|
|
|
case atCFAPlusOffset:
|
|
|
|
case isCFAPlusOffset:
|
[x86] Fix issues with a realigned stack in MSVC compiled applications
Summary:
This patch fixes issues with a stack realignment.
MSVC maintains two frame pointers (`ebx` and `ebp`) for a realigned stack - one
is used for access to function parameters, while another is used for access to
locals. To support this the patch:
- adds an alternative frame pointer (`ebx`);
- considers stack realignment instructions (e.g. `and esp, -32`);
- along with CFA (Canonical Frame Address) which point to the position next to
the saved return address (or to the first parameter on the stack) introduces
AFA (Aligned Frame Address) which points to the position of the stack pointer
right after realignment. AFA is used for access to registers saved after the
realignment (see the test);
Here is an example of the code with the realignment:
```
struct __declspec(align(256)) OverAligned {
char c;
};
void foo(int foo_arg) {
OverAligned oa_foo = { 1 };
auto aaa_foo = 1234;
}
void bar(int bar_arg) {
OverAligned oa_bar = { 2 };
auto aaa_bar = 5678;
foo(1111);
}
int main() {
bar(2222);
return 0;
}
```
and here is the `bar` disassembly:
```
push ebx
mov ebx, esp
sub esp, 8
and esp, -100h
add esp, 4
push ebp
mov ebp, [ebx+4]
mov [esp+4], ebp
mov ebp, esp
sub esp, 200h
mov byte ptr [ebp-200h], 2
mov dword ptr [ebp-4], 5678
push 1111 ; foo_arg
call j_?foo@@YAXH@Z ; foo(int)
add esp, 4
mov esp, ebp
pop ebp
mov esp, ebx
pop ebx
retn
```
Reviewers: labath, zturner, jasonmolenda, stella.stamenova
Reviewed By: jasonmolenda
Subscribers: abidh, lldb-commits
Tags: #lldb
Differential Revision: https://reviews.llvm.org/D53435
llvm-svn: 345577
2018-10-30 18:07:08 +08:00
|
|
|
case atAFAPlusOffset:
|
|
|
|
case isAFAPlusOffset:
|
2011-05-12 02:39:18 +08:00
|
|
|
return m_location.offset == rhs.m_location.offset;
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2011-05-12 02:39:18 +08:00
|
|
|
case inOtherRegister:
|
|
|
|
return m_location.reg_num == rhs.m_location.reg_num;
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2011-05-12 02:39:18 +08:00
|
|
|
case atDWARFExpression:
|
|
|
|
case isDWARFExpression:
|
|
|
|
if (m_location.expr.length == rhs.m_location.expr.length)
|
|
|
|
return !memcmp(m_location.expr.opcodes, rhs.m_location.expr.opcodes,
|
|
|
|
m_location.expr.length);
|
|
|
|
break;
|
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2010-09-10 15:49:16 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// This function doesn't copy the dwarf expression bytes; they must remain in
|
2018-05-01 00:49:04 +08:00
|
|
|
// allocated memory for the lifespan of this UnwindPlan object.
|
2010-09-10 15:49:16 +08:00
|
|
|
void UnwindPlan::Row::RegisterLocation::SetAtDWARFExpression(
|
|
|
|
const uint8_t *opcodes, uint32_t len) {
|
|
|
|
m_type = atDWARFExpression;
|
|
|
|
m_location.expr.opcodes = opcodes;
|
|
|
|
m_location.expr.length = len;
|
|
|
|
}
|
|
|
|
|
|
|
|
// This function doesn't copy the dwarf expression bytes; they must remain in
|
2018-05-01 00:49:04 +08:00
|
|
|
// allocated memory for the lifespan of this UnwindPlan object.
|
2010-09-10 15:49:16 +08:00
|
|
|
void UnwindPlan::Row::RegisterLocation::SetIsDWARFExpression(
|
|
|
|
const uint8_t *opcodes, uint32_t len) {
|
|
|
|
m_type = isDWARFExpression;
|
|
|
|
m_location.expr.opcodes = opcodes;
|
2011-05-12 02:39:18 +08:00
|
|
|
m_location.expr.length = len;
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
|
2019-04-23 17:16:51 +08:00
|
|
|
static llvm::Optional<std::pair<lldb::ByteOrder, uint32_t>>
|
|
|
|
GetByteOrderAndAddrSize(Thread *thread) {
|
|
|
|
if (!thread)
|
|
|
|
return llvm::None;
|
|
|
|
ProcessSP process_sp = thread->GetProcess();
|
|
|
|
if (!process_sp)
|
|
|
|
return llvm::None;
|
|
|
|
ArchSpec arch = process_sp->GetTarget().GetArchitecture();
|
|
|
|
return std::make_pair(arch.GetByteOrder(), arch.GetAddressByteSize());
|
|
|
|
}
|
|
|
|
|
|
|
|
static void DumpDWARFExpr(Stream &s, llvm::ArrayRef<uint8_t> expr, Thread *thread) {
|
|
|
|
if (auto order_and_width = GetByteOrderAndAddrSize(thread)) {
|
2020-05-25 21:59:48 +08:00
|
|
|
llvm::DataExtractor data(expr, order_and_width->first == eByteOrderLittle,
|
|
|
|
order_and_width->second);
|
|
|
|
llvm::DWARFExpression(data, order_and_width->second, llvm::dwarf::DWARF32)
|
2020-10-24 10:19:36 +08:00
|
|
|
.print(s.AsRawOstream(), llvm::DIDumpOptions(), nullptr, nullptr);
|
2019-04-23 17:16:51 +08:00
|
|
|
} else
|
|
|
|
s.PutCString("dwarf-expr");
|
|
|
|
}
|
|
|
|
|
2014-04-20 21:17:36 +08:00
|
|
|
void UnwindPlan::Row::RegisterLocation::Dump(Stream &s,
|
2011-05-12 02:39:18 +08:00
|
|
|
const UnwindPlan *unwind_plan,
|
|
|
|
const UnwindPlan::Row *row,
|
|
|
|
Thread *thread,
|
2010-09-10 15:49:16 +08:00
|
|
|
bool verbose) const {
|
2011-05-12 02:39:18 +08:00
|
|
|
switch (m_type) {
|
|
|
|
case unspecified:
|
|
|
|
if (verbose)
|
|
|
|
s.PutCString("=<unspec>");
|
2015-02-23 18:19:16 +08:00
|
|
|
else
|
|
|
|
s.PutCString("=!");
|
|
|
|
break;
|
|
|
|
case undefined:
|
|
|
|
if (verbose)
|
2012-11-30 05:49:15 +08:00
|
|
|
s.PutCString("=<undef>");
|
2010-09-10 15:49:16 +08:00
|
|
|
else
|
2015-01-13 14:04:04 +08:00
|
|
|
s.PutCString("=?");
|
2016-09-07 04:57:50 +08:00
|
|
|
break;
|
2011-05-12 02:39:18 +08:00
|
|
|
case same:
|
|
|
|
s.PutCString("= <same>");
|
2016-09-07 04:57:50 +08:00
|
|
|
break;
|
|
|
|
|
2015-01-13 14:04:04 +08:00
|
|
|
case atCFAPlusOffset:
|
2010-09-10 15:49:16 +08:00
|
|
|
case isCFAPlusOffset: {
|
2011-05-12 02:39:18 +08:00
|
|
|
s.PutChar('=');
|
2015-01-13 14:04:04 +08:00
|
|
|
if (m_type == atCFAPlusOffset)
|
2011-05-12 02:39:18 +08:00
|
|
|
s.PutChar('[');
|
2015-01-13 14:04:04 +08:00
|
|
|
s.Printf("CFA%+d", m_location.offset);
|
2010-09-10 15:49:16 +08:00
|
|
|
if (m_type == atCFAPlusOffset)
|
2011-05-12 02:39:18 +08:00
|
|
|
s.PutChar(']');
|
2010-09-10 15:49:16 +08:00
|
|
|
} break;
|
2016-09-07 04:57:50 +08:00
|
|
|
|
[x86] Fix issues with a realigned stack in MSVC compiled applications
Summary:
This patch fixes issues with a stack realignment.
MSVC maintains two frame pointers (`ebx` and `ebp`) for a realigned stack - one
is used for access to function parameters, while another is used for access to
locals. To support this the patch:
- adds an alternative frame pointer (`ebx`);
- considers stack realignment instructions (e.g. `and esp, -32`);
- along with CFA (Canonical Frame Address) which point to the position next to
the saved return address (or to the first parameter on the stack) introduces
AFA (Aligned Frame Address) which points to the position of the stack pointer
right after realignment. AFA is used for access to registers saved after the
realignment (see the test);
Here is an example of the code with the realignment:
```
struct __declspec(align(256)) OverAligned {
char c;
};
void foo(int foo_arg) {
OverAligned oa_foo = { 1 };
auto aaa_foo = 1234;
}
void bar(int bar_arg) {
OverAligned oa_bar = { 2 };
auto aaa_bar = 5678;
foo(1111);
}
int main() {
bar(2222);
return 0;
}
```
and here is the `bar` disassembly:
```
push ebx
mov ebx, esp
sub esp, 8
and esp, -100h
add esp, 4
push ebp
mov ebp, [ebx+4]
mov [esp+4], ebp
mov ebp, esp
sub esp, 200h
mov byte ptr [ebp-200h], 2
mov dword ptr [ebp-4], 5678
push 1111 ; foo_arg
call j_?foo@@YAXH@Z ; foo(int)
add esp, 4
mov esp, ebp
pop ebp
mov esp, ebx
pop ebx
retn
```
Reviewers: labath, zturner, jasonmolenda, stella.stamenova
Reviewed By: jasonmolenda
Subscribers: abidh, lldb-commits
Tags: #lldb
Differential Revision: https://reviews.llvm.org/D53435
llvm-svn: 345577
2018-10-30 18:07:08 +08:00
|
|
|
case atAFAPlusOffset:
|
|
|
|
case isAFAPlusOffset: {
|
|
|
|
s.PutChar('=');
|
|
|
|
if (m_type == atAFAPlusOffset)
|
|
|
|
s.PutChar('[');
|
|
|
|
s.Printf("AFA%+d", m_location.offset);
|
|
|
|
if (m_type == atAFAPlusOffset)
|
|
|
|
s.PutChar(']');
|
|
|
|
} break;
|
|
|
|
|
2014-11-12 23:14:03 +08:00
|
|
|
case inOtherRegister: {
|
2010-09-10 15:49:16 +08:00
|
|
|
const RegisterInfo *other_reg_info = nullptr;
|
|
|
|
if (unwind_plan)
|
|
|
|
other_reg_info = unwind_plan->GetRegisterInfo(thread, m_location.reg_num);
|
|
|
|
if (other_reg_info)
|
|
|
|
s.Printf("=%s", other_reg_info->name);
|
2016-09-07 04:57:50 +08:00
|
|
|
else
|
2010-09-10 15:49:16 +08:00
|
|
|
s.Printf("=reg(%u)", m_location.reg_num);
|
2016-09-07 04:57:50 +08:00
|
|
|
} break;
|
|
|
|
|
2010-09-10 15:49:16 +08:00
|
|
|
case atDWARFExpression:
|
|
|
|
case isDWARFExpression: {
|
|
|
|
s.PutChar('=');
|
|
|
|
if (m_type == atDWARFExpression)
|
2019-04-23 17:16:51 +08:00
|
|
|
s.PutChar('[');
|
|
|
|
DumpDWARFExpr(
|
|
|
|
s, llvm::makeArrayRef(m_location.expr.opcodes, m_location.expr.length),
|
|
|
|
thread);
|
|
|
|
if (m_type == atDWARFExpression)
|
|
|
|
s.PutChar(']');
|
2010-09-10 15:49:16 +08:00
|
|
|
} break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-13 14:04:04 +08:00
|
|
|
static void DumpRegisterName(Stream &s, const UnwindPlan *unwind_plan,
|
|
|
|
Thread *thread, uint32_t reg_num) {
|
|
|
|
const RegisterInfo *reg_info = unwind_plan->GetRegisterInfo(thread, reg_num);
|
|
|
|
if (reg_info)
|
|
|
|
s.PutCString(reg_info->name);
|
2016-09-07 04:57:50 +08:00
|
|
|
else
|
2015-01-13 14:04:04 +08:00
|
|
|
s.Printf("reg(%u)", reg_num);
|
|
|
|
}
|
|
|
|
|
[x86] Fix issues with a realigned stack in MSVC compiled applications
Summary:
This patch fixes issues with a stack realignment.
MSVC maintains two frame pointers (`ebx` and `ebp`) for a realigned stack - one
is used for access to function parameters, while another is used for access to
locals. To support this the patch:
- adds an alternative frame pointer (`ebx`);
- considers stack realignment instructions (e.g. `and esp, -32`);
- along with CFA (Canonical Frame Address) which point to the position next to
the saved return address (or to the first parameter on the stack) introduces
AFA (Aligned Frame Address) which points to the position of the stack pointer
right after realignment. AFA is used for access to registers saved after the
realignment (see the test);
Here is an example of the code with the realignment:
```
struct __declspec(align(256)) OverAligned {
char c;
};
void foo(int foo_arg) {
OverAligned oa_foo = { 1 };
auto aaa_foo = 1234;
}
void bar(int bar_arg) {
OverAligned oa_bar = { 2 };
auto aaa_bar = 5678;
foo(1111);
}
int main() {
bar(2222);
return 0;
}
```
and here is the `bar` disassembly:
```
push ebx
mov ebx, esp
sub esp, 8
and esp, -100h
add esp, 4
push ebp
mov ebp, [ebx+4]
mov [esp+4], ebp
mov ebp, esp
sub esp, 200h
mov byte ptr [ebp-200h], 2
mov dword ptr [ebp-4], 5678
push 1111 ; foo_arg
call j_?foo@@YAXH@Z ; foo(int)
add esp, 4
mov esp, ebp
pop ebp
mov esp, ebx
pop ebx
retn
```
Reviewers: labath, zturner, jasonmolenda, stella.stamenova
Reviewed By: jasonmolenda
Subscribers: abidh, lldb-commits
Tags: #lldb
Differential Revision: https://reviews.llvm.org/D53435
llvm-svn: 345577
2018-10-30 18:07:08 +08:00
|
|
|
bool UnwindPlan::Row::FAValue::
|
|
|
|
operator==(const UnwindPlan::Row::FAValue &rhs) const {
|
2010-09-10 15:49:16 +08:00
|
|
|
if (m_type == rhs.m_type) {
|
2015-02-23 18:19:16 +08:00
|
|
|
switch (m_type) {
|
2010-09-10 15:49:16 +08:00
|
|
|
case unspecified:
|
Unwind: Add a stack scanning mechanism to support win32 unwinding
Summary:
Windows unwinding is weird. The unwind rules do not (always) describe
the precise layout of the stack, but rather expect the debugger to scan
the stack for something which looks like a plausible return address, and
the unwind based on that. The reason this works somewhat reliably is
because the the unwinder also has access to the frame sizes of the
functions on the stack. This allows it (in most cases) to skip function
pointers in local variables or function arguments, which could otherwise
be mistaken for return addresses.
Implementing this kind of unwind mechanism in lldb was a bit challenging
because we expect to be able to statically describe (in the UnwindPlan)
structure, the layout of the stack for any given instruction. Giving a
precise desription of this is not possible, because it requires
correlating information from two functions -- the pushed arguments to a
function are considered a part of the callers stack frame, and their
size needs to be considered when unwinding the caller, but they are only
present in the unwind entry of the callee. The callee may end up being
in a completely different module, or it may not even be possible to
determine it statically (indirect calls).
This patch implements this functionality by introducing a couple of new
APIs:
SymbolFile::GetParameterStackSize - return the amount of stack space
taken up by parameters of this function.
SymbolFile::GetOwnFrameSize - the size of this function's frame. This
excludes the parameters, but includes stuff like local variables and
spilled registers.
These functions are then used by the unwinder to compute the estimated
location of the return address. This address is not always exact,
because the stack may contain some additional values -- for instance, if
we're getting ready to call a function then the stack will also contain
partially set up arguments, but we will not know their size because we
haven't called the function yet. For this reason the unwinder will crawl
up the stack from the return address position, and look for something
that looks like a possible return address. Currently, we assume that
something is a valid return address if it ends up pointing to an
executable section.
All of this logic kicks in when the UnwindPlan sets the value of CFA as
"isHeuristicallyDetected", which is also the final new API here. Right
now, only SymbolFileBreakpad implements these APIs, but in the future
SymbolFilePDB will use them too.
Differential Revision: https://reviews.llvm.org/D66638
llvm-svn: 373072
2019-09-27 20:10:06 +08:00
|
|
|
case isRaSearch:
|
|
|
|
return m_value.ra_search_offset == rhs.m_value.ra_search_offset;
|
2010-09-10 15:49:16 +08:00
|
|
|
|
2011-05-12 02:39:18 +08:00
|
|
|
case isRegisterPlusOffset:
|
|
|
|
return m_value.reg.offset == rhs.m_value.reg.offset;
|
|
|
|
|
|
|
|
case isRegisterDereferenced:
|
|
|
|
return m_value.reg.reg_num == rhs.m_value.reg.reg_num;
|
|
|
|
|
|
|
|
case isDWARFExpression:
|
|
|
|
if (m_value.expr.length == rhs.m_value.expr.length)
|
|
|
|
return !memcmp(m_value.expr.opcodes, rhs.m_value.expr.opcodes,
|
|
|
|
m_value.expr.length);
|
|
|
|
break;
|
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2011-05-12 02:39:18 +08:00
|
|
|
return false;
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
|
[x86] Fix issues with a realigned stack in MSVC compiled applications
Summary:
This patch fixes issues with a stack realignment.
MSVC maintains two frame pointers (`ebx` and `ebp`) for a realigned stack - one
is used for access to function parameters, while another is used for access to
locals. To support this the patch:
- adds an alternative frame pointer (`ebx`);
- considers stack realignment instructions (e.g. `and esp, -32`);
- along with CFA (Canonical Frame Address) which point to the position next to
the saved return address (or to the first parameter on the stack) introduces
AFA (Aligned Frame Address) which points to the position of the stack pointer
right after realignment. AFA is used for access to registers saved after the
realignment (see the test);
Here is an example of the code with the realignment:
```
struct __declspec(align(256)) OverAligned {
char c;
};
void foo(int foo_arg) {
OverAligned oa_foo = { 1 };
auto aaa_foo = 1234;
}
void bar(int bar_arg) {
OverAligned oa_bar = { 2 };
auto aaa_bar = 5678;
foo(1111);
}
int main() {
bar(2222);
return 0;
}
```
and here is the `bar` disassembly:
```
push ebx
mov ebx, esp
sub esp, 8
and esp, -100h
add esp, 4
push ebp
mov ebp, [ebx+4]
mov [esp+4], ebp
mov ebp, esp
sub esp, 200h
mov byte ptr [ebp-200h], 2
mov dword ptr [ebp-4], 5678
push 1111 ; foo_arg
call j_?foo@@YAXH@Z ; foo(int)
add esp, 4
mov esp, ebp
pop ebp
mov esp, ebx
pop ebx
retn
```
Reviewers: labath, zturner, jasonmolenda, stella.stamenova
Reviewed By: jasonmolenda
Subscribers: abidh, lldb-commits
Tags: #lldb
Differential Revision: https://reviews.llvm.org/D53435
llvm-svn: 345577
2018-10-30 18:07:08 +08:00
|
|
|
void UnwindPlan::Row::FAValue::Dump(Stream &s, const UnwindPlan *unwind_plan,
|
2015-02-23 18:19:16 +08:00
|
|
|
Thread *thread) const {
|
|
|
|
switch (m_type) {
|
|
|
|
case isRegisterPlusOffset:
|
|
|
|
DumpRegisterName(s, unwind_plan, thread, m_value.reg.reg_num);
|
|
|
|
s.Printf("%+3d", m_value.reg.offset);
|
2016-09-07 04:57:50 +08:00
|
|
|
break;
|
2015-02-23 18:19:16 +08:00
|
|
|
case isRegisterDereferenced:
|
2011-05-12 02:39:18 +08:00
|
|
|
s.PutChar('[');
|
2015-02-23 18:19:16 +08:00
|
|
|
DumpRegisterName(s, unwind_plan, thread, m_value.reg.reg_num);
|
2011-05-12 02:39:18 +08:00
|
|
|
s.PutChar(']');
|
2016-09-07 04:57:50 +08:00
|
|
|
break;
|
2015-02-23 18:19:16 +08:00
|
|
|
case isDWARFExpression:
|
2019-04-23 17:16:51 +08:00
|
|
|
DumpDWARFExpr(s,
|
|
|
|
llvm::makeArrayRef(m_value.expr.opcodes, m_value.expr.length),
|
|
|
|
thread);
|
2016-09-07 04:57:50 +08:00
|
|
|
break;
|
Unwind: Add a stack scanning mechanism to support win32 unwinding
Summary:
Windows unwinding is weird. The unwind rules do not (always) describe
the precise layout of the stack, but rather expect the debugger to scan
the stack for something which looks like a plausible return address, and
the unwind based on that. The reason this works somewhat reliably is
because the the unwinder also has access to the frame sizes of the
functions on the stack. This allows it (in most cases) to skip function
pointers in local variables or function arguments, which could otherwise
be mistaken for return addresses.
Implementing this kind of unwind mechanism in lldb was a bit challenging
because we expect to be able to statically describe (in the UnwindPlan)
structure, the layout of the stack for any given instruction. Giving a
precise desription of this is not possible, because it requires
correlating information from two functions -- the pushed arguments to a
function are considered a part of the callers stack frame, and their
size needs to be considered when unwinding the caller, but they are only
present in the unwind entry of the callee. The callee may end up being
in a completely different module, or it may not even be possible to
determine it statically (indirect calls).
This patch implements this functionality by introducing a couple of new
APIs:
SymbolFile::GetParameterStackSize - return the amount of stack space
taken up by parameters of this function.
SymbolFile::GetOwnFrameSize - the size of this function's frame. This
excludes the parameters, but includes stuff like local variables and
spilled registers.
These functions are then used by the unwinder to compute the estimated
location of the return address. This address is not always exact,
because the stack may contain some additional values -- for instance, if
we're getting ready to call a function then the stack will also contain
partially set up arguments, but we will not know their size because we
haven't called the function yet. For this reason the unwinder will crawl
up the stack from the return address position, and look for something
that looks like a possible return address. Currently, we assume that
something is a valid return address if it ends up pointing to an
executable section.
All of this logic kicks in when the UnwindPlan sets the value of CFA as
"isHeuristicallyDetected", which is also the final new API here. Right
now, only SymbolFileBreakpad implements these APIs, but in the future
SymbolFilePDB will use them too.
Differential Revision: https://reviews.llvm.org/D66638
llvm-svn: 373072
2019-09-27 20:10:06 +08:00
|
|
|
case unspecified:
|
2015-02-23 18:19:16 +08:00
|
|
|
s.PutCString("unspecified");
|
2016-09-07 04:57:50 +08:00
|
|
|
break;
|
Unwind: Add a stack scanning mechanism to support win32 unwinding
Summary:
Windows unwinding is weird. The unwind rules do not (always) describe
the precise layout of the stack, but rather expect the debugger to scan
the stack for something which looks like a plausible return address, and
the unwind based on that. The reason this works somewhat reliably is
because the the unwinder also has access to the frame sizes of the
functions on the stack. This allows it (in most cases) to skip function
pointers in local variables or function arguments, which could otherwise
be mistaken for return addresses.
Implementing this kind of unwind mechanism in lldb was a bit challenging
because we expect to be able to statically describe (in the UnwindPlan)
structure, the layout of the stack for any given instruction. Giving a
precise desription of this is not possible, because it requires
correlating information from two functions -- the pushed arguments to a
function are considered a part of the callers stack frame, and their
size needs to be considered when unwinding the caller, but they are only
present in the unwind entry of the callee. The callee may end up being
in a completely different module, or it may not even be possible to
determine it statically (indirect calls).
This patch implements this functionality by introducing a couple of new
APIs:
SymbolFile::GetParameterStackSize - return the amount of stack space
taken up by parameters of this function.
SymbolFile::GetOwnFrameSize - the size of this function's frame. This
excludes the parameters, but includes stuff like local variables and
spilled registers.
These functions are then used by the unwinder to compute the estimated
location of the return address. This address is not always exact,
because the stack may contain some additional values -- for instance, if
we're getting ready to call a function then the stack will also contain
partially set up arguments, but we will not know their size because we
haven't called the function yet. For this reason the unwinder will crawl
up the stack from the return address position, and look for something
that looks like a possible return address. Currently, we assume that
something is a valid return address if it ends up pointing to an
executable section.
All of this logic kicks in when the UnwindPlan sets the value of CFA as
"isHeuristicallyDetected", which is also the final new API here. Right
now, only SymbolFileBreakpad implements these APIs, but in the future
SymbolFilePDB will use them too.
Differential Revision: https://reviews.llvm.org/D66638
llvm-svn: 373072
2019-09-27 20:10:06 +08:00
|
|
|
case isRaSearch:
|
|
|
|
s.Printf("RaSearch@SP%+d", m_value.ra_search_offset);
|
|
|
|
break;
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-09-10 15:49:16 +08:00
|
|
|
void UnwindPlan::Row::Clear() {
|
2015-02-23 18:19:16 +08:00
|
|
|
m_cfa_value.SetUnspecified();
|
[x86] Fix issues with a realigned stack in MSVC compiled applications
Summary:
This patch fixes issues with a stack realignment.
MSVC maintains two frame pointers (`ebx` and `ebp`) for a realigned stack - one
is used for access to function parameters, while another is used for access to
locals. To support this the patch:
- adds an alternative frame pointer (`ebx`);
- considers stack realignment instructions (e.g. `and esp, -32`);
- along with CFA (Canonical Frame Address) which point to the position next to
the saved return address (or to the first parameter on the stack) introduces
AFA (Aligned Frame Address) which points to the position of the stack pointer
right after realignment. AFA is used for access to registers saved after the
realignment (see the test);
Here is an example of the code with the realignment:
```
struct __declspec(align(256)) OverAligned {
char c;
};
void foo(int foo_arg) {
OverAligned oa_foo = { 1 };
auto aaa_foo = 1234;
}
void bar(int bar_arg) {
OverAligned oa_bar = { 2 };
auto aaa_bar = 5678;
foo(1111);
}
int main() {
bar(2222);
return 0;
}
```
and here is the `bar` disassembly:
```
push ebx
mov ebx, esp
sub esp, 8
and esp, -100h
add esp, 4
push ebp
mov ebp, [ebx+4]
mov [esp+4], ebp
mov ebp, esp
sub esp, 200h
mov byte ptr [ebp-200h], 2
mov dword ptr [ebp-4], 5678
push 1111 ; foo_arg
call j_?foo@@YAXH@Z ; foo(int)
add esp, 4
mov esp, ebp
pop ebp
mov esp, ebx
pop ebx
retn
```
Reviewers: labath, zturner, jasonmolenda, stella.stamenova
Reviewed By: jasonmolenda
Subscribers: abidh, lldb-commits
Tags: #lldb
Differential Revision: https://reviews.llvm.org/D53435
llvm-svn: 345577
2018-10-30 18:07:08 +08:00
|
|
|
m_afa_value.SetUnspecified();
|
2010-09-10 15:49:16 +08:00
|
|
|
m_offset = 0;
|
|
|
|
m_register_locations.clear();
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
|
2015-02-23 18:19:16 +08:00
|
|
|
void UnwindPlan::Row::Dump(Stream &s, const UnwindPlan *unwind_plan,
|
2011-05-12 02:39:18 +08:00
|
|
|
Thread *thread, addr_t base_addr) const {
|
|
|
|
if (base_addr != LLDB_INVALID_ADDRESS)
|
2012-11-30 05:49:15 +08:00
|
|
|
s.Printf("0x%16.16" PRIx64 ": CFA=", base_addr + GetOffset());
|
2016-09-07 04:57:50 +08:00
|
|
|
else
|
2012-11-30 05:49:15 +08:00
|
|
|
s.Printf("%4" PRId64 ": CFA=", GetOffset());
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2015-02-23 18:19:16 +08:00
|
|
|
m_cfa_value.Dump(s, unwind_plan, thread);
|
[x86] Fix issues with a realigned stack in MSVC compiled applications
Summary:
This patch fixes issues with a stack realignment.
MSVC maintains two frame pointers (`ebx` and `ebp`) for a realigned stack - one
is used for access to function parameters, while another is used for access to
locals. To support this the patch:
- adds an alternative frame pointer (`ebx`);
- considers stack realignment instructions (e.g. `and esp, -32`);
- along with CFA (Canonical Frame Address) which point to the position next to
the saved return address (or to the first parameter on the stack) introduces
AFA (Aligned Frame Address) which points to the position of the stack pointer
right after realignment. AFA is used for access to registers saved after the
realignment (see the test);
Here is an example of the code with the realignment:
```
struct __declspec(align(256)) OverAligned {
char c;
};
void foo(int foo_arg) {
OverAligned oa_foo = { 1 };
auto aaa_foo = 1234;
}
void bar(int bar_arg) {
OverAligned oa_bar = { 2 };
auto aaa_bar = 5678;
foo(1111);
}
int main() {
bar(2222);
return 0;
}
```
and here is the `bar` disassembly:
```
push ebx
mov ebx, esp
sub esp, 8
and esp, -100h
add esp, 4
push ebp
mov ebp, [ebx+4]
mov [esp+4], ebp
mov ebp, esp
sub esp, 200h
mov byte ptr [ebp-200h], 2
mov dword ptr [ebp-4], 5678
push 1111 ; foo_arg
call j_?foo@@YAXH@Z ; foo(int)
add esp, 4
mov esp, ebp
pop ebp
mov esp, ebx
pop ebx
retn
```
Reviewers: labath, zturner, jasonmolenda, stella.stamenova
Reviewed By: jasonmolenda
Subscribers: abidh, lldb-commits
Tags: #lldb
Differential Revision: https://reviews.llvm.org/D53435
llvm-svn: 345577
2018-10-30 18:07:08 +08:00
|
|
|
|
|
|
|
if (!m_afa_value.IsUnspecified()) {
|
|
|
|
s.Printf(" AFA=");
|
|
|
|
m_afa_value.Dump(s, unwind_plan, thread);
|
|
|
|
}
|
|
|
|
|
2015-02-23 18:19:16 +08:00
|
|
|
s.Printf(" => ");
|
2010-09-10 15:49:16 +08:00
|
|
|
for (collection::const_iterator idx = m_register_locations.begin();
|
|
|
|
idx != m_register_locations.end(); ++idx) {
|
2015-02-23 18:19:16 +08:00
|
|
|
DumpRegisterName(s, unwind_plan, thread, idx->first);
|
2011-05-12 02:39:18 +08:00
|
|
|
const bool verbose = false;
|
|
|
|
idx->second.Dump(s, unwind_plan, this, thread, verbose);
|
|
|
|
s.PutChar(' ');
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
s.EOL();
|
|
|
|
}
|
|
|
|
|
[x86] Fix issues with a realigned stack in MSVC compiled applications
Summary:
This patch fixes issues with a stack realignment.
MSVC maintains two frame pointers (`ebx` and `ebp`) for a realigned stack - one
is used for access to function parameters, while another is used for access to
locals. To support this the patch:
- adds an alternative frame pointer (`ebx`);
- considers stack realignment instructions (e.g. `and esp, -32`);
- along with CFA (Canonical Frame Address) which point to the position next to
the saved return address (or to the first parameter on the stack) introduces
AFA (Aligned Frame Address) which points to the position of the stack pointer
right after realignment. AFA is used for access to registers saved after the
realignment (see the test);
Here is an example of the code with the realignment:
```
struct __declspec(align(256)) OverAligned {
char c;
};
void foo(int foo_arg) {
OverAligned oa_foo = { 1 };
auto aaa_foo = 1234;
}
void bar(int bar_arg) {
OverAligned oa_bar = { 2 };
auto aaa_bar = 5678;
foo(1111);
}
int main() {
bar(2222);
return 0;
}
```
and here is the `bar` disassembly:
```
push ebx
mov ebx, esp
sub esp, 8
and esp, -100h
add esp, 4
push ebp
mov ebp, [ebx+4]
mov [esp+4], ebp
mov ebp, esp
sub esp, 200h
mov byte ptr [ebp-200h], 2
mov dword ptr [ebp-4], 5678
push 1111 ; foo_arg
call j_?foo@@YAXH@Z ; foo(int)
add esp, 4
mov esp, ebp
pop ebp
mov esp, ebx
pop ebx
retn
```
Reviewers: labath, zturner, jasonmolenda, stella.stamenova
Reviewed By: jasonmolenda
Subscribers: abidh, lldb-commits
Tags: #lldb
Differential Revision: https://reviews.llvm.org/D53435
llvm-svn: 345577
2018-10-30 18:07:08 +08:00
|
|
|
UnwindPlan::Row::Row()
|
|
|
|
: m_offset(0), m_cfa_value(), m_afa_value(), m_register_locations() {}
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2011-05-12 02:39:18 +08:00
|
|
|
bool UnwindPlan::Row::GetRegisterInfo(
|
|
|
|
uint32_t reg_num,
|
|
|
|
UnwindPlan::Row::RegisterLocation ®ister_location) const {
|
|
|
|
collection::const_iterator pos = m_register_locations.find(reg_num);
|
2015-01-13 14:04:04 +08:00
|
|
|
if (pos != m_register_locations.end()) {
|
2011-05-12 02:39:18 +08:00
|
|
|
register_location = pos->second;
|
|
|
|
return true;
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2010-09-10 15:49:16 +08:00
|
|
|
return false;
|
2011-05-12 02:39:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void UnwindPlan::Row::RemoveRegisterInfo(uint32_t reg_num) {
|
|
|
|
collection::const_iterator pos = m_register_locations.find(reg_num);
|
|
|
|
if (pos != m_register_locations.end()) {
|
|
|
|
m_register_locations.erase(pos);
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2011-05-12 02:39:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void UnwindPlan::Row::SetRegisterInfo(
|
|
|
|
uint32_t reg_num,
|
|
|
|
const UnwindPlan::Row::RegisterLocation register_location) {
|
|
|
|
m_register_locations[reg_num] = register_location;
|
|
|
|
}
|
|
|
|
|
2012-07-17 09:57:24 +08:00
|
|
|
bool UnwindPlan::Row::SetRegisterLocationToAtCFAPlusOffset(uint32_t reg_num,
|
2015-02-23 18:19:16 +08:00
|
|
|
int32_t offset,
|
2011-05-12 02:39:18 +08:00
|
|
|
bool can_replace) {
|
2015-02-23 18:19:16 +08:00
|
|
|
if (!can_replace &&
|
|
|
|
m_register_locations.find(reg_num) != m_register_locations.end())
|
2010-09-10 15:49:16 +08:00
|
|
|
return false;
|
2011-05-12 02:39:18 +08:00
|
|
|
RegisterLocation reg_loc;
|
|
|
|
reg_loc.SetAtCFAPlusOffset(offset);
|
2015-02-23 18:19:16 +08:00
|
|
|
m_register_locations[reg_num] = reg_loc;
|
2011-05-12 02:39:18 +08:00
|
|
|
return true;
|
2012-07-17 09:57:24 +08:00
|
|
|
}
|
|
|
|
|
2012-07-19 04:37:53 +08:00
|
|
|
bool UnwindPlan::Row::SetRegisterLocationToIsCFAPlusOffset(uint32_t reg_num,
|
2011-05-12 02:39:18 +08:00
|
|
|
int32_t offset,
|
2012-07-19 04:37:53 +08:00
|
|
|
bool can_replace) {
|
|
|
|
if (!can_replace &&
|
|
|
|
m_register_locations.find(reg_num) != m_register_locations.end())
|
2011-05-12 02:39:18 +08:00
|
|
|
return false;
|
|
|
|
RegisterLocation reg_loc;
|
|
|
|
reg_loc.SetIsCFAPlusOffset(offset);
|
|
|
|
m_register_locations[reg_num] = reg_loc;
|
|
|
|
return true;
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
|
2012-07-19 04:37:53 +08:00
|
|
|
bool UnwindPlan::Row::SetRegisterLocationToUndefined(
|
2011-05-12 02:39:18 +08:00
|
|
|
uint32_t reg_num, bool can_replace, bool can_replace_only_if_unspecified) {
|
|
|
|
collection::iterator pos = m_register_locations.find(reg_num);
|
|
|
|
collection::iterator end = m_register_locations.end();
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2011-05-12 02:39:18 +08:00
|
|
|
if (pos != end) {
|
|
|
|
if (!can_replace)
|
|
|
|
return false;
|
2012-07-19 04:37:53 +08:00
|
|
|
if (can_replace_only_if_unspecified && !pos->second.IsUnspecified())
|
2011-05-12 02:39:18 +08:00
|
|
|
return false;
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2011-05-12 02:39:18 +08:00
|
|
|
RegisterLocation reg_loc;
|
|
|
|
reg_loc.SetUndefined();
|
|
|
|
m_register_locations[reg_num] = reg_loc;
|
|
|
|
return true;
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
|
2012-07-19 04:37:53 +08:00
|
|
|
bool UnwindPlan::Row::SetRegisterLocationToUnspecified(uint32_t reg_num,
|
2010-09-10 15:49:16 +08:00
|
|
|
bool can_replace) {
|
2012-07-19 04:37:53 +08:00
|
|
|
if (!can_replace &&
|
|
|
|
m_register_locations.find(reg_num) != m_register_locations.end())
|
|
|
|
return false;
|
|
|
|
RegisterLocation reg_loc;
|
|
|
|
reg_loc.SetUnspecified();
|
|
|
|
m_register_locations[reg_num] = reg_loc;
|
2011-05-12 02:39:18 +08:00
|
|
|
return true;
|
2010-09-10 15:49:16 +08:00
|
|
|
}
|
|
|
|
|
2016-02-10 18:42:13 +08:00
|
|
|
bool UnwindPlan::Row::SetRegisterLocationToRegister(uint32_t reg_num,
|
|
|
|
uint32_t other_reg_num,
|
|
|
|
bool can_replace) {
|
|
|
|
if (!can_replace &&
|
|
|
|
m_register_locations.find(reg_num) != m_register_locations.end())
|
2011-05-12 02:39:18 +08:00
|
|
|
return false;
|
|
|
|
RegisterLocation reg_loc;
|
2014-08-26 04:29:09 +08:00
|
|
|
reg_loc.SetInRegister(other_reg_num);
|
|
|
|
m_register_locations[reg_num] = reg_loc;
|
2016-02-10 18:42:13 +08:00
|
|
|
return true;
|
2014-08-26 04:29:09 +08:00
|
|
|
}
|
|
|
|
|
2011-05-12 02:39:18 +08:00
|
|
|
bool UnwindPlan::Row::SetRegisterLocationToSame(uint32_t reg_num,
|
|
|
|
bool must_replace) {
|
|
|
|
if (must_replace &&
|
|
|
|
m_register_locations.find(reg_num) == m_register_locations.end())
|
|
|
|
return false;
|
|
|
|
RegisterLocation reg_loc;
|
|
|
|
reg_loc.SetSame();
|
|
|
|
m_register_locations[reg_num] = reg_loc;
|
|
|
|
return true;
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
|
2015-02-23 18:19:16 +08:00
|
|
|
bool UnwindPlan::Row::operator==(const UnwindPlan::Row &rhs) const {
|
[x86] Fix issues with a realigned stack in MSVC compiled applications
Summary:
This patch fixes issues with a stack realignment.
MSVC maintains two frame pointers (`ebx` and `ebp`) for a realigned stack - one
is used for access to function parameters, while another is used for access to
locals. To support this the patch:
- adds an alternative frame pointer (`ebx`);
- considers stack realignment instructions (e.g. `and esp, -32`);
- along with CFA (Canonical Frame Address) which point to the position next to
the saved return address (or to the first parameter on the stack) introduces
AFA (Aligned Frame Address) which points to the position of the stack pointer
right after realignment. AFA is used for access to registers saved after the
realignment (see the test);
Here is an example of the code with the realignment:
```
struct __declspec(align(256)) OverAligned {
char c;
};
void foo(int foo_arg) {
OverAligned oa_foo = { 1 };
auto aaa_foo = 1234;
}
void bar(int bar_arg) {
OverAligned oa_bar = { 2 };
auto aaa_bar = 5678;
foo(1111);
}
int main() {
bar(2222);
return 0;
}
```
and here is the `bar` disassembly:
```
push ebx
mov ebx, esp
sub esp, 8
and esp, -100h
add esp, 4
push ebp
mov ebp, [ebx+4]
mov [esp+4], ebp
mov ebp, esp
sub esp, 200h
mov byte ptr [ebp-200h], 2
mov dword ptr [ebp-4], 5678
push 1111 ; foo_arg
call j_?foo@@YAXH@Z ; foo(int)
add esp, 4
mov esp, ebp
pop ebp
mov esp, ebx
pop ebx
retn
```
Reviewers: labath, zturner, jasonmolenda, stella.stamenova
Reviewed By: jasonmolenda
Subscribers: abidh, lldb-commits
Tags: #lldb
Differential Revision: https://reviews.llvm.org/D53435
llvm-svn: 345577
2018-10-30 18:07:08 +08:00
|
|
|
return m_offset == rhs.m_offset &&
|
|
|
|
m_cfa_value == rhs.m_cfa_value &&
|
|
|
|
m_afa_value == rhs.m_afa_value &&
|
|
|
|
m_register_locations == rhs.m_register_locations;
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
|
2012-07-14 12:52:53 +08:00
|
|
|
void UnwindPlan::AppendRow(const UnwindPlan::RowSP &row_sp) {
|
2016-07-13 07:07:50 +08:00
|
|
|
if (m_row_list.empty() ||
|
2015-06-24 19:27:32 +08:00
|
|
|
m_row_list.back()->GetOffset() != row_sp->GetOffset())
|
2012-07-19 04:37:53 +08:00
|
|
|
m_row_list.push_back(row_sp);
|
2016-09-07 04:57:50 +08:00
|
|
|
else
|
2015-06-24 19:27:32 +08:00
|
|
|
m_row_list.back() = row_sp;
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
|
2011-05-12 02:39:18 +08:00
|
|
|
void UnwindPlan::InsertRow(const UnwindPlan::RowSP &row_sp,
|
2016-02-10 18:42:13 +08:00
|
|
|
bool replace_existing) {
|
2011-05-12 02:39:18 +08:00
|
|
|
collection::iterator it = m_row_list.begin();
|
2010-09-10 15:49:16 +08:00
|
|
|
while (it != m_row_list.end()) {
|
2014-08-26 04:29:09 +08:00
|
|
|
RowSP row = *it;
|
2015-06-24 19:27:32 +08:00
|
|
|
if (row->GetOffset() >= row_sp->GetOffset())
|
2016-09-07 04:57:50 +08:00
|
|
|
break;
|
|
|
|
it++;
|
|
|
|
}
|
2015-06-24 19:27:32 +08:00
|
|
|
if (it == m_row_list.end() || (*it)->GetOffset() != row_sp->GetOffset())
|
|
|
|
m_row_list.insert(it, row_sp);
|
2016-02-10 18:42:13 +08:00
|
|
|
else if (replace_existing)
|
|
|
|
*it = row_sp;
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
|
2010-09-10 15:49:16 +08:00
|
|
|
UnwindPlan::RowSP UnwindPlan::GetRowForFunctionOffset(int offset) const {
|
2012-07-14 12:52:53 +08:00
|
|
|
RowSP row;
|
2011-01-09 05:19:00 +08:00
|
|
|
if (!m_row_list.empty()) {
|
|
|
|
if (offset == -1)
|
2012-07-14 12:52:53 +08:00
|
|
|
row = m_row_list.back();
|
2016-09-07 04:57:50 +08:00
|
|
|
else {
|
2011-01-09 05:19:00 +08:00
|
|
|
collection::const_iterator pos, end = m_row_list.end();
|
|
|
|
for (pos = m_row_list.begin(); pos != end; ++pos) {
|
2014-04-02 11:51:35 +08:00
|
|
|
if ((*pos)->GetOffset() <= static_cast<lldb::offset_t>(offset))
|
2012-07-14 12:52:53 +08:00
|
|
|
row = *pos;
|
2010-09-10 15:49:16 +08:00
|
|
|
else
|
2011-01-09 05:19:00 +08:00
|
|
|
break;
|
2010-09-10 15:49:16 +08:00
|
|
|
}
|
2016-07-13 07:07:50 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2012-07-14 12:52:53 +08:00
|
|
|
return row;
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
|
2010-09-10 15:49:16 +08:00
|
|
|
bool UnwindPlan::IsValidRowIndex(uint32_t idx) const {
|
2011-05-12 02:39:18 +08:00
|
|
|
return idx < m_row_list.size();
|
2010-09-10 15:49:16 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2011-05-12 02:39:18 +08:00
|
|
|
const UnwindPlan::RowSP UnwindPlan::GetRowAtIndex(uint32_t idx) const {
|
|
|
|
if (idx < m_row_list.size())
|
|
|
|
return m_row_list[idx];
|
|
|
|
else {
|
2016-07-13 07:07:50 +08:00
|
|
|
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND));
|
2019-07-25 01:56:10 +08:00
|
|
|
LLDB_LOGF(log,
|
|
|
|
"error: UnwindPlan::GetRowAtIndex(idx = %u) invalid index "
|
|
|
|
"(number rows is %u)",
|
|
|
|
idx, (uint32_t)m_row_list.size());
|
2010-09-10 15:49:16 +08:00
|
|
|
return UnwindPlan::RowSP();
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-09-10 15:49:16 +08:00
|
|
|
const UnwindPlan::RowSP UnwindPlan::GetLastRow() const {
|
2010-10-25 19:12:07 +08:00
|
|
|
if (m_row_list.empty()) {
|
|
|
|
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND));
|
2019-07-25 01:56:10 +08:00
|
|
|
LLDB_LOGF(log, "UnwindPlan::GetLastRow() when rows are empty");
|
2016-07-13 07:07:50 +08:00
|
|
|
return UnwindPlan::RowSP();
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2010-10-25 19:12:07 +08:00
|
|
|
return m_row_list.back();
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
|
2010-10-25 19:12:07 +08:00
|
|
|
int UnwindPlan::GetRowCount() const { return m_row_list.size(); }
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2010-10-25 19:12:07 +08:00
|
|
|
void UnwindPlan::SetPlanValidAddressRange(const AddressRange &range) {
|
2010-09-10 15:49:16 +08:00
|
|
|
if (range.GetBaseAddress().IsValid() && range.GetByteSize() != 0)
|
2010-10-25 19:12:07 +08:00
|
|
|
m_plan_valid_address_range = range;
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
|
2010-09-10 15:49:16 +08:00
|
|
|
bool UnwindPlan::PlanValidAtAddress(Address addr) {
|
2013-12-03 12:46:27 +08:00
|
|
|
// If this UnwindPlan has no rows, it is an invalid UnwindPlan.
|
|
|
|
if (GetRowCount() == 0) {
|
|
|
|
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND));
|
|
|
|
if (log) {
|
2013-12-04 05:59:39 +08:00
|
|
|
StreamString s;
|
2014-04-20 21:17:36 +08:00
|
|
|
if (addr.Dump(&s, nullptr, Address::DumpStyleSectionNameOffset)) {
|
2019-07-25 01:56:10 +08:00
|
|
|
LLDB_LOGF(log,
|
|
|
|
"UnwindPlan is invalid -- no unwind rows for UnwindPlan "
|
|
|
|
"'%s' at address %s",
|
|
|
|
m_source_name.GetCString(), s.GetData());
|
2013-12-04 05:59:39 +08:00
|
|
|
} else {
|
2019-07-25 01:56:10 +08:00
|
|
|
LLDB_LOGF(log,
|
|
|
|
"UnwindPlan is invalid -- no unwind rows for UnwindPlan '%s'",
|
|
|
|
m_source_name.GetCString());
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2013-12-03 12:46:27 +08:00
|
|
|
}
|
|
|
|
return false;
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
|
2013-12-03 12:46:27 +08:00
|
|
|
// If the 0th Row of unwind instructions is missing, or if it doesn't provide
|
|
|
|
// a register to use to find the Canonical Frame Address, this is not a valid
|
|
|
|
// UnwindPlan.
|
2015-02-23 18:19:16 +08:00
|
|
|
if (GetRowAtIndex(0).get() == nullptr ||
|
2015-02-23 18:29:01 +08:00
|
|
|
GetRowAtIndex(0)->GetCFAValue().GetValueType() ==
|
[x86] Fix issues with a realigned stack in MSVC compiled applications
Summary:
This patch fixes issues with a stack realignment.
MSVC maintains two frame pointers (`ebx` and `ebp`) for a realigned stack - one
is used for access to function parameters, while another is used for access to
locals. To support this the patch:
- adds an alternative frame pointer (`ebx`);
- considers stack realignment instructions (e.g. `and esp, -32`);
- along with CFA (Canonical Frame Address) which point to the position next to
the saved return address (or to the first parameter on the stack) introduces
AFA (Aligned Frame Address) which points to the position of the stack pointer
right after realignment. AFA is used for access to registers saved after the
realignment (see the test);
Here is an example of the code with the realignment:
```
struct __declspec(align(256)) OverAligned {
char c;
};
void foo(int foo_arg) {
OverAligned oa_foo = { 1 };
auto aaa_foo = 1234;
}
void bar(int bar_arg) {
OverAligned oa_bar = { 2 };
auto aaa_bar = 5678;
foo(1111);
}
int main() {
bar(2222);
return 0;
}
```
and here is the `bar` disassembly:
```
push ebx
mov ebx, esp
sub esp, 8
and esp, -100h
add esp, 4
push ebp
mov ebp, [ebx+4]
mov [esp+4], ebp
mov ebp, esp
sub esp, 200h
mov byte ptr [ebp-200h], 2
mov dword ptr [ebp-4], 5678
push 1111 ; foo_arg
call j_?foo@@YAXH@Z ; foo(int)
add esp, 4
mov esp, ebp
pop ebp
mov esp, ebx
pop ebx
retn
```
Reviewers: labath, zturner, jasonmolenda, stella.stamenova
Reviewed By: jasonmolenda
Subscribers: abidh, lldb-commits
Tags: #lldb
Differential Revision: https://reviews.llvm.org/D53435
llvm-svn: 345577
2018-10-30 18:07:08 +08:00
|
|
|
Row::FAValue::unspecified) {
|
2013-12-03 12:46:27 +08:00
|
|
|
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND));
|
|
|
|
if (log) {
|
2013-12-04 05:59:39 +08:00
|
|
|
StreamString s;
|
2014-04-20 21:17:36 +08:00
|
|
|
if (addr.Dump(&s, nullptr, Address::DumpStyleSectionNameOffset)) {
|
2019-07-25 01:56:10 +08:00
|
|
|
LLDB_LOGF(log,
|
|
|
|
"UnwindPlan is invalid -- no CFA register defined in row 0 "
|
|
|
|
"for UnwindPlan '%s' at address %s",
|
|
|
|
m_source_name.GetCString(), s.GetData());
|
2013-12-04 05:59:39 +08:00
|
|
|
} else {
|
2019-07-25 01:56:10 +08:00
|
|
|
LLDB_LOGF(log,
|
|
|
|
"UnwindPlan is invalid -- no CFA register defined in row 0 "
|
|
|
|
"for UnwindPlan '%s'",
|
|
|
|
m_source_name.GetCString());
|
2013-12-04 05:59:39 +08:00
|
|
|
}
|
2013-12-03 12:46:27 +08:00
|
|
|
}
|
2010-09-10 15:49:16 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-11-18 10:27:42 +08:00
|
|
|
if (!m_plan_valid_address_range.GetBaseAddress().IsValid() ||
|
|
|
|
m_plan_valid_address_range.GetByteSize() == 0)
|
2011-01-09 05:19:00 +08:00
|
|
|
return true;
|
2010-10-25 19:12:07 +08:00
|
|
|
|
|
|
|
if (!addr.IsValid())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
if (m_plan_valid_address_range.ContainsFileAddress(addr))
|
|
|
|
return true;
|
2011-05-12 02:39:18 +08:00
|
|
|
|
|
|
|
return false;
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
|
2011-05-12 02:39:18 +08:00
|
|
|
void UnwindPlan::Dump(Stream &s, Thread *thread, lldb::addr_t base_addr) const {
|
2010-10-25 19:12:07 +08:00
|
|
|
if (!m_source_name.IsEmpty()) {
|
2011-05-12 02:39:18 +08:00
|
|
|
s.Printf("This UnwindPlan originally sourced from %s\n",
|
2013-12-04 05:59:39 +08:00
|
|
|
m_source_name.GetCString());
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2014-11-18 10:27:42 +08:00
|
|
|
if (m_lsda_address.IsValid() && m_personality_func_addr.IsValid()) {
|
|
|
|
TargetSP target_sp(thread->CalculateTarget());
|
|
|
|
addr_t lsda_load_addr = m_lsda_address.GetLoadAddress(target_sp.get());
|
|
|
|
addr_t personality_func_load_addr =
|
2011-05-12 02:39:18 +08:00
|
|
|
m_personality_func_addr.GetLoadAddress(target_sp.get());
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2014-11-18 10:27:42 +08:00
|
|
|
if (lsda_load_addr != LLDB_INVALID_ADDRESS &&
|
|
|
|
personality_func_load_addr != LLDB_INVALID_ADDRESS) {
|
|
|
|
s.Printf("LSDA address 0x%" PRIx64
|
|
|
|
", personality routine is at address 0x%" PRIx64 "\n",
|
|
|
|
lsda_load_addr, personality_func_load_addr);
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
}
|
2014-11-18 10:27:42 +08:00
|
|
|
s.Printf("This UnwindPlan is sourced from the compiler: ");
|
|
|
|
switch (m_plan_is_sourced_from_compiler) {
|
|
|
|
case eLazyBoolYes:
|
|
|
|
s.Printf("yes.\n");
|
2016-09-07 04:57:50 +08:00
|
|
|
break;
|
2014-11-18 10:27:42 +08:00
|
|
|
case eLazyBoolNo:
|
|
|
|
s.Printf("no.\n");
|
2016-09-07 04:57:50 +08:00
|
|
|
break;
|
2014-11-18 10:27:42 +08:00
|
|
|
case eLazyBoolCalculate:
|
|
|
|
s.Printf("not specified.\n");
|
2016-09-07 04:57:50 +08:00
|
|
|
break;
|
|
|
|
}
|
2014-11-18 10:27:42 +08:00
|
|
|
s.Printf("This UnwindPlan is valid at all instruction locations: ");
|
|
|
|
switch (m_plan_is_valid_at_all_instruction_locations) {
|
|
|
|
case eLazyBoolYes:
|
|
|
|
s.Printf("yes.\n");
|
2016-09-07 04:57:50 +08:00
|
|
|
break;
|
2014-11-18 10:27:42 +08:00
|
|
|
case eLazyBoolNo:
|
|
|
|
s.Printf("no.\n");
|
2016-09-07 04:57:50 +08:00
|
|
|
break;
|
2014-11-18 10:27:42 +08:00
|
|
|
case eLazyBoolCalculate:
|
|
|
|
s.Printf("not specified.\n");
|
2016-09-07 04:57:50 +08:00
|
|
|
break;
|
|
|
|
}
|
2020-08-26 11:53:01 +08:00
|
|
|
s.Printf("This UnwindPlan is for a trap handler function: ");
|
|
|
|
switch (m_plan_is_for_signal_trap) {
|
|
|
|
case eLazyBoolYes:
|
|
|
|
s.Printf("yes.\n");
|
|
|
|
break;
|
|
|
|
case eLazyBoolNo:
|
|
|
|
s.Printf("no.\n");
|
|
|
|
break;
|
|
|
|
case eLazyBoolCalculate:
|
|
|
|
s.Printf("not specified.\n");
|
|
|
|
break;
|
|
|
|
}
|
2010-10-25 19:12:07 +08:00
|
|
|
if (m_plan_valid_address_range.GetBaseAddress().IsValid() &&
|
2011-05-12 02:39:18 +08:00
|
|
|
m_plan_valid_address_range.GetByteSize() > 0) {
|
|
|
|
s.PutCString("Address range of this UnwindPlan: ");
|
2014-11-18 10:27:42 +08:00
|
|
|
TargetSP target_sp(thread->CalculateTarget());
|
2012-02-21 08:09:25 +08:00
|
|
|
m_plan_valid_address_range.Dump(&s, target_sp.get(),
|
|
|
|
Address::DumpStyleSectionNameOffset);
|
2016-09-07 04:57:50 +08:00
|
|
|
s.EOL();
|
|
|
|
}
|
2011-05-12 02:39:18 +08:00
|
|
|
collection::const_iterator pos, begin = m_row_list.begin(),
|
|
|
|
end = m_row_list.end();
|
|
|
|
for (pos = begin; pos != end; ++pos) {
|
|
|
|
s.Printf("row[%u]: ", (uint32_t)std::distance(begin, pos));
|
2012-07-14 12:52:53 +08:00
|
|
|
(*pos)->Dump(s, this, thread, base_addr);
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-05-12 02:39:18 +08:00
|
|
|
void UnwindPlan::SetSourceName(const char *source) {
|
2010-10-25 19:12:07 +08:00
|
|
|
m_source_name = ConstString(source);
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
|
2010-10-25 19:12:07 +08:00
|
|
|
ConstString UnwindPlan::GetSourceName() const { return m_source_name; }
|
2016-09-07 04:57:50 +08:00
|
|
|
|
2015-02-23 18:19:16 +08:00
|
|
|
const RegisterInfo *UnwindPlan::GetRegisterInfo(Thread *thread,
|
|
|
|
uint32_t unwind_reg) const {
|
2011-05-12 02:39:18 +08:00
|
|
|
if (thread) {
|
|
|
|
RegisterContext *reg_ctx = thread->GetRegisterContext().get();
|
|
|
|
if (reg_ctx) {
|
|
|
|
uint32_t reg;
|
|
|
|
if (m_register_kind == eRegisterKindLLDB)
|
|
|
|
reg = unwind_reg;
|
|
|
|
else
|
|
|
|
reg = reg_ctx->ConvertRegisterKindToRegisterNumber(m_register_kind,
|
|
|
|
unwind_reg);
|
|
|
|
if (reg != LLDB_INVALID_REGNUM)
|
|
|
|
return reg_ctx->GetRegisterInfoAtIndex(reg);
|
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
2014-04-20 21:17:36 +08:00
|
|
|
return nullptr;
|
2011-05-12 02:39:18 +08:00
|
|
|
}
|