diff options
| author | Sean Callanan <scallanan@apple.com> | 2016-09-06 04:48:36 +0000 |
|---|---|---|
| committer | Sean Callanan <scallanan@apple.com> | 2016-09-06 04:48:36 +0000 |
| commit | 4740a734bb4a4f20ae4895ded32585e54bb87afb (patch) | |
| tree | 9884944c80582b90d8ff4fdbf64fd8716766f8e2 /lldb/source/Expression/DWARFExpression.cpp | |
| parent | 24dac6afe29ccbd4455dc44d6d6bc85b04bfbc31 (diff) | |
| download | bcm5719-llvm-4740a734bb4a4f20ae4895ded32585e54bb87afb.tar.gz bcm5719-llvm-4740a734bb4a4f20ae4895ded32585e54bb87afb.zip | |
Added the "frame diagnose" command and use its output to make crash info better.
When a process stops due to a crash, we get the crashing instruction and the
crashing memory location (if there is one). From the user's perspective it is
often unclear what the reason for the crash is in a symbolic sense.
To address this, I have added new fuctionality to StackFrame to parse the
disassembly and reconstruct the sequence of dereferneces and offsets that were
applied to a known variable (or fuction retrn value) to obtain the invalid
pointer.
This makes use of enhancements in the disassembler, as well as new information
provided by the DWARF expression infrastructure, and is exposed through a
"frame diagnose" command. It is also used to provide symbolic information, when
available, in the event of a crash.
The algorithm is very rudimentary, and it needs a bunch of work, including
- better parsing for assembly, preferably with help from LLVM
- support for non-Apple platforms
- cleanup of the algorithm core, preferably to make it all work in terms of
Operands instead of register/offset pairs
- improvement of the GetExpressioPath() logic to make prettier expression
paths, and
- better handling of vtables.
I welcome all suggestios, improvements, and testcases.
llvm-svn: 280692
Diffstat (limited to 'lldb/source/Expression/DWARFExpression.cpp')
| -rw-r--r-- | lldb/source/Expression/DWARFExpression.cpp | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp index b81d60e9b06..23a922c491b 100644 --- a/lldb/source/Expression/DWARFExpression.cpp +++ b/lldb/source/Expression/DWARFExpression.cpp @@ -30,6 +30,8 @@ #include "lldb/Host/Endian.h" #include "lldb/Host/Host.h" +#include "lldb/Symbol/Function.h" + #include "lldb/Target/ABI.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Process.h" @@ -3336,3 +3338,149 @@ DWARFExpression::PrintDWARFLocationList(Stream &s, offset += loc_length; } } + +bool +DWARFExpression::GetOpAndEndOffsets(StackFrame &frame, lldb::offset_t &op_offset, lldb::offset_t &end_offset) +{ + SymbolContext sc = frame.GetSymbolContext(eSymbolContextFunction); + if (!sc.function) + { + return false; + } + + addr_t loclist_base_file_addr = sc.function->GetAddressRange().GetBaseAddress().GetFileAddress(); + if (loclist_base_file_addr == LLDB_INVALID_ADDRESS) + { + return false; + } + + addr_t pc_file_addr = frame.GetFrameCodeAddress().GetFileAddress(); + lldb::offset_t opcodes_offset, opcodes_length; + if (!GetLocation(loclist_base_file_addr, pc_file_addr, opcodes_offset, opcodes_length)) + { + return false; + } + + if (opcodes_length == 0) + { + return false; + } + + op_offset = opcodes_offset; + end_offset = opcodes_offset + opcodes_length; + return true; +} + +bool +DWARFExpression::IsRegister(StackFrame &frame, + const RegisterInfo *®ister_info) +{ + lldb::offset_t op_offset; + lldb::offset_t end_offset; + if (!GetOpAndEndOffsets(frame, op_offset, end_offset)) + { + return false; + } + + if (!m_data.ValidOffset(op_offset) || op_offset >= end_offset) + { + return false; + } + + RegisterContextSP reg_ctx_sp = frame.GetRegisterContext(); + if (!reg_ctx_sp) + { + return false; + } + + DataExtractor opcodes = m_data; + uint8_t opcode = opcodes.GetU8(&op_offset); + + if (opcode >= DW_OP_reg0 && opcode <= DW_OP_breg31) + { + register_info = reg_ctx_sp->GetRegisterInfo(m_reg_kind, opcode - DW_OP_reg0); + return register_info != nullptr; + } + switch (opcode) + { + default: + return false; + case DW_OP_regx: + { + uint32_t reg_num = m_data.GetULEB128(&op_offset); + register_info = reg_ctx_sp->GetRegisterInfo(m_reg_kind, reg_num); + return register_info != nullptr; + } + } +} + +bool +DWARFExpression::IsDereferenceOfRegister(StackFrame &frame, + const RegisterInfo *®ister_info, + int64_t &offset) +{ + lldb::offset_t op_offset; + lldb::offset_t end_offset; + if (!GetOpAndEndOffsets(frame, op_offset, end_offset)) + { + return false; + } + + if (!m_data.ValidOffset(op_offset) || op_offset >= end_offset) + { + return false; + } + + RegisterContextSP reg_ctx_sp = frame.GetRegisterContext(); + if (!reg_ctx_sp) + { + return false; + } + + DataExtractor opcodes = m_data; + uint8_t opcode = opcodes.GetU8(&op_offset); + + switch (opcode) + { + default: + return false; + case DW_OP_bregx: + { + uint32_t reg_num = static_cast<uint32_t>(opcodes.GetULEB128(&op_offset)); + int64_t breg_offset = opcodes.GetSLEB128(&op_offset); + + const RegisterInfo *reg_info = reg_ctx_sp->GetRegisterInfo(m_reg_kind, reg_num); + if (!reg_info) + { + return false; + } + + register_info = reg_info; + offset = breg_offset; + return true; + } + case DW_OP_fbreg: + { + int64_t fbreg_offset = opcodes.GetSLEB128(&op_offset); + + DWARFExpression *dwarf_expression = frame.GetFrameBaseExpression(nullptr); + + if (!dwarf_expression) + { + return false; + } + + const RegisterInfo *fbr_info; + + if (!dwarf_expression->IsRegister(frame, fbr_info)) + { + return false; + } + + register_info = fbr_info; + offset = fbreg_offset; + return true; + } + } +} + |

