Re-commit the changes from r282565 that I had to back out because of

a linux bot test failure.  That one is fixed; hopefully there won't
be any others turned up this time.

The eh_frame augmentation code wasn't working right after the 
reorg/rewrite of the classes.  It works correctly now for the one
test that was failing - but we'll see what the test bots come up
with. 

<rdar://problem/28509178> 

llvm-svn: 282659
This commit is contained in:
Jason Molenda 2016-09-29 01:00:16 +00:00
parent d72dd1fc4e
commit 74b8fbcba7
10 changed files with 1690 additions and 1201 deletions

View File

@ -928,6 +928,8 @@
AF33B4BE1C1FA441001B28D9 /* NetBSDSignals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF33B4BC1C1FA441001B28D9 /* NetBSDSignals.cpp */; };
AF33B4BF1C1FA441001B28D9 /* NetBSDSignals.h in Headers */ = {isa = PBXBuildFile; fileRef = AF33B4BD1C1FA441001B28D9 /* NetBSDSignals.h */; };
AF37E10A17C861F20061E18E /* ProcessRunLock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF37E10917C861F20061E18E /* ProcessRunLock.cpp */; };
AF415AE71D949E4400FCE0D4 /* x86AssemblyInspectionEngine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF415AE51D949E4400FCE0D4 /* x86AssemblyInspectionEngine.cpp */; };
AF415AE81D949E4400FCE0D4 /* x86AssemblyInspectionEngine.h in Headers */ = {isa = PBXBuildFile; fileRef = AF415AE61D949E4400FCE0D4 /* x86AssemblyInspectionEngine.h */; };
AF45FDE518A1F3AC0007051C /* AppleGetThreadItemInfoHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF45FDE318A1F3AC0007051C /* AppleGetThreadItemInfoHandler.cpp */; };
AF6335E21C87B21E00F7D554 /* SymbolFilePDB.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF6335E01C87B21E00F7D554 /* SymbolFilePDB.cpp */; };
AF6335E31C87B21E00F7D554 /* SymbolFilePDB.h in Headers */ = {isa = PBXBuildFile; fileRef = AF6335E11C87B21E00F7D554 /* SymbolFilePDB.h */; };
@ -953,9 +955,12 @@
AFC234091AF85CE100CDE8B6 /* CommandObjectLanguage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AFC234061AF85CE000CDE8B6 /* CommandObjectLanguage.cpp */; };
AFCB2BBD1BF577F40018B553 /* PythonExceptionState.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AFCB2BBB1BF577F40018B553 /* PythonExceptionState.cpp */; };
AFCB2BBE1BF577F40018B553 /* PythonExceptionState.h in Headers */ = {isa = PBXBuildFile; fileRef = AFCB2BBC1BF577F40018B553 /* PythonExceptionState.h */; };
AFD65C811D9B5B2E00D93120 /* RegisterContextMinidump_x86_64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AFD65C7F1D9B5B2E00D93120 /* RegisterContextMinidump_x86_64.cpp */; };
AFD65C821D9B5B2E00D93120 /* RegisterContextMinidump_x86_64.h in Headers */ = {isa = PBXBuildFile; fileRef = AFD65C801D9B5B2E00D93120 /* RegisterContextMinidump_x86_64.h */; };
AFDCDBCB19DD0F42005EA55E /* SBExecutionContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 940B02F419DC96CB00AD0F52 /* SBExecutionContext.h */; settings = {ATTRIBUTES = (Public, ); }; };
AFDFDFD119E34D3400EAE509 /* ConnectionFileDescriptorPosix.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AFDFDFD019E34D3400EAE509 /* ConnectionFileDescriptorPosix.cpp */; };
AFEC3362194A8ABA00FF05C6 /* StructuredData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AFEC3361194A8ABA00FF05C6 /* StructuredData.cpp */; };
AFEC5FD81D94F9380076A480 /* Testx86AssemblyInspectionEngine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AFEC5FD51D94F9380076A480 /* Testx86AssemblyInspectionEngine.cpp */; };
AFF87C87150FF669000E1742 /* com.apple.debugserver.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = AFF87C86150FF669000E1742 /* com.apple.debugserver.plist */; };
AFF87C8F150FF688000E1742 /* com.apple.debugserver.applist.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = AFF87C8E150FF688000E1742 /* com.apple.debugserver.applist.plist */; };
B207C4931429607D00F36E4E /* CommandObjectWatchpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B207C4921429607D00F36E4E /* CommandObjectWatchpoint.cpp */; };
@ -2946,6 +2951,8 @@
AF3F54BF1B3BA5D500186E73 /* RegisterContextPOSIXProcessMonitor_powerpc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegisterContextPOSIXProcessMonitor_powerpc.h; sourceTree = "<group>"; };
AF3F54C01B3BA5D500186E73 /* RegisterContextPOSIXProcessMonitor_x86.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RegisterContextPOSIXProcessMonitor_x86.cpp; sourceTree = "<group>"; };
AF3F54C11B3BA5D500186E73 /* RegisterContextPOSIXProcessMonitor_x86.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegisterContextPOSIXProcessMonitor_x86.h; sourceTree = "<group>"; };
AF415AE51D949E4400FCE0D4 /* x86AssemblyInspectionEngine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = x86AssemblyInspectionEngine.cpp; sourceTree = "<group>"; };
AF415AE61D949E4400FCE0D4 /* x86AssemblyInspectionEngine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = x86AssemblyInspectionEngine.h; sourceTree = "<group>"; };
AF45E1FC1BF57C8D000563EB /* PythonTestSuite.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PythonTestSuite.cpp; sourceTree = "<group>"; };
AF45E1FD1BF57C8D000563EB /* PythonTestSuite.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PythonTestSuite.h; sourceTree = "<group>"; };
AF45FDE318A1F3AC0007051C /* AppleGetThreadItemInfoHandler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AppleGetThreadItemInfoHandler.cpp; sourceTree = "<group>"; };
@ -2992,8 +2999,11 @@
AFC234071AF85CE000CDE8B6 /* CommandObjectLanguage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandObjectLanguage.h; path = source/Commands/CommandObjectLanguage.h; sourceTree = "<group>"; };
AFCB2BBB1BF577F40018B553 /* PythonExceptionState.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PythonExceptionState.cpp; path = ScriptInterpreter/Python/PythonExceptionState.cpp; sourceTree = "<group>"; };
AFCB2BBC1BF577F40018B553 /* PythonExceptionState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PythonExceptionState.h; path = ScriptInterpreter/Python/PythonExceptionState.h; sourceTree = "<group>"; };
AFD65C7F1D9B5B2E00D93120 /* RegisterContextMinidump_x86_64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RegisterContextMinidump_x86_64.cpp; sourceTree = "<group>"; };
AFD65C801D9B5B2E00D93120 /* RegisterContextMinidump_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegisterContextMinidump_x86_64.h; sourceTree = "<group>"; };
AFDFDFD019E34D3400EAE509 /* ConnectionFileDescriptorPosix.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ConnectionFileDescriptorPosix.cpp; sourceTree = "<group>"; };
AFEC3361194A8ABA00FF05C6 /* StructuredData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StructuredData.cpp; path = source/Core/StructuredData.cpp; sourceTree = "<group>"; };
AFEC5FD51D94F9380076A480 /* Testx86AssemblyInspectionEngine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Testx86AssemblyInspectionEngine.cpp; path = UnwindAssembly/x86/Testx86AssemblyInspectionEngine.cpp; sourceTree = "<group>"; };
AFF87C86150FF669000E1742 /* com.apple.debugserver.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = com.apple.debugserver.plist; path = tools/debugserver/source/com.apple.debugserver.plist; sourceTree = "<group>"; };
AFF87C8A150FF677000E1742 /* com.apple.debugserver.applist.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = com.apple.debugserver.applist.plist; path = tools/debugserver/source/com.apple.debugserver.applist.plist; sourceTree = "<group>"; };
AFF87C8C150FF680000E1742 /* com.apple.debugserver.applist.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = com.apple.debugserver.applist.plist; path = tools/debugserver/source/com.apple.debugserver.applist.plist; sourceTree = "<group>"; };
@ -3227,6 +3237,7 @@
2321F93F1BDD33D800BA9A93 /* ScriptInterpreter */,
23CB15091D66CF2B00EDDDE1 /* Symbol */,
23CB150A1D66CF3200EDDDE1 /* SymbolFile */,
AFEC5FD31D94F9130076A480 /* UnwindAssembly */,
2321F9421BDD343A00BA9A93 /* Utility */,
);
path = unittests;
@ -3527,6 +3538,8 @@
23E2E5351D9048E7006F38BB /* minidump */ = {
isa = PBXGroup;
children = (
AFD65C7F1D9B5B2E00D93120 /* RegisterContextMinidump_x86_64.cpp */,
AFD65C801D9B5B2E00D93120 /* RegisterContextMinidump_x86_64.h */,
23E2E5361D9048FB006F38BB /* CMakeLists.txt */,
23E2E5371D9048FB006F38BB /* MinidumpParser.cpp */,
23E2E5381D9048FB006F38BB /* MinidumpParser.h */,
@ -4405,6 +4418,8 @@
2692BA17136611CD00F9E14D /* x86 */ = {
isa = PBXGroup;
children = (
AF415AE51D949E4400FCE0D4 /* x86AssemblyInspectionEngine.cpp */,
AF415AE61D949E4400FCE0D4 /* x86AssemblyInspectionEngine.h */,
263E949D13661AE400E7D1CE /* UnwindAssembly-x86.cpp */,
263E949E13661AE400E7D1CE /* UnwindAssembly-x86.h */,
);
@ -6283,6 +6298,22 @@
name = "SysV-ppc64";
sourceTree = "<group>";
};
AFEC5FD31D94F9130076A480 /* UnwindAssembly */ = {
isa = PBXGroup;
children = (
AFEC5FD51D94F9380076A480 /* Testx86AssemblyInspectionEngine.cpp */,
AFEC5FD41D94F9270076A480 /* x86 */,
);
name = UnwindAssembly;
sourceTree = "<group>";
};
AFEC5FD41D94F9270076A480 /* x86 */ = {
isa = PBXGroup;
children = (
);
name = x86;
sourceTree = "<group>";
};
E769331B1A94D10E00C73337 /* lldb-server */ = {
isa = PBXGroup;
children = (
@ -6400,7 +6431,9 @@
4984BA181B979C08008658D4 /* ExpressionVariable.h in Headers */,
26C7C4841BFFEA7E009BD01F /* WindowsMiniDump.h in Headers */,
30B38A001CAAA6D7009524E3 /* ClangUtil.h in Headers */,
AFD65C821D9B5B2E00D93120 /* RegisterContextMinidump_x86_64.h in Headers */,
238F2BA11D2C835A001FF92A /* StructuredDataPlugin.h in Headers */,
AF415AE81D949E4400FCE0D4 /* x86AssemblyInspectionEngine.h in Headers */,
AF8AD62F1BEC28A400150209 /* PlatformAppleTVSimulator.h in Headers */,
238F2BA91D2C85FA001FF92A /* StructuredDataDarwinLog.h in Headers */,
AF8AD63A1BEC28C400150209 /* PlatformRemoteAppleWatch.h in Headers */,
@ -6890,6 +6923,7 @@
23CB153E1D66DA9300EDDDE1 /* PythonDataObjectsTests.cpp in Sources */,
23CB153F1D66DA9300EDDDE1 /* SymbolsTest.cpp in Sources */,
23E2E52B1D9037E6006F38BB /* ModuleCacheTest.cpp in Sources */,
AFEC5FD81D94F9380076A480 /* Testx86AssemblyInspectionEngine.cpp in Sources */,
23CB15401D66DA9300EDDDE1 /* TestClangASTContext.cpp in Sources */,
23CB15411D66DA9300EDDDE1 /* StringExtractorTest.cpp in Sources */,
23CB15421D66DA9300EDDDE1 /* TaskPoolTest.cpp in Sources */,
@ -6989,6 +7023,7 @@
26D1804216CEDF0700EDFB5B /* TimeSpecTimeout.cpp in Sources */,
2689FFDA13353D9D00698AC0 /* lldb.cpp in Sources */,
4C0083401B9F9BA900D5CF24 /* UtilityFunction.cpp in Sources */,
AF415AE71D949E4400FCE0D4 /* x86AssemblyInspectionEngine.cpp in Sources */,
26474CCD18D0CB5B0073DEBA /* RegisterContextPOSIX_x86.cpp in Sources */,
AEB0E4591BD6E9F800B24093 /* LLVMUserExpression.cpp in Sources */,
2689FFEF13353DB600698AC0 /* Breakpoint.cpp in Sources */,
@ -7547,6 +7582,7 @@
23D0658F1D4A7BEE0008EDE6 /* RenderScriptExpressionOpts.cpp in Sources */,
945215DF17F639EE00521C0B /* ValueObjectPrinter.cpp in Sources */,
26EFB61B1BFE8D3E00544801 /* PlatformNetBSD.cpp in Sources */,
AFD65C811D9B5B2E00D93120 /* RegisterContextMinidump_x86_64.cpp in Sources */,
260CC64815D0440D002BF2E0 /* OptionValueArgs.cpp in Sources */,
260CC64915D0440D002BF2E0 /* OptionValueArray.cpp in Sources */,
260CC64A15D0440D002BF2E0 /* OptionValueBoolean.cpp in Sources */,

View File

@ -1,3 +1,4 @@
add_lldb_library(lldbPluginUnwindAssemblyX86
UnwindAssembly-x86.cpp
x86AssemblyInspectionEngine.cpp
)

File diff suppressed because it is too large Load Diff

View File

@ -13,7 +13,7 @@
// C Includes
// C++ Includes
// Other libraries and framework includes
#include "llvm-c/Disassembler.h"
#include "x86AssemblyInspectionEngine.h"
// Project includes
#include "lldb/Target/UnwindAssembly.h"
@ -62,10 +62,11 @@ public:
uint32_t GetPluginVersion() override;
private:
UnwindAssembly_x86(const lldb_private::ArchSpec &arch, int cpu);
UnwindAssembly_x86(const lldb_private::ArchSpec &arch);
int m_cpu;
lldb_private::ArchSpec m_arch;
lldb_private::x86AssemblyInspectionEngine *m_assembly_inspection_engine;
};
#endif // liblldb_UnwindAssembly_x86_h_

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,178 @@
//===-- x86AssemblyInspectionEngine.h ---------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef liblldb_x86AssemblyInspectionEngine_h_
#define liblldb_x86AssemblyInspectionEngine_h_
#include "llvm-c/Disassembler.h"
#include "lldb/lldb-enumerations.h"
#include "lldb/lldb-forward.h"
#include "lldb/lldb-private.h"
#include "lldb/Core/ArchSpec.h"
#include "lldb/Core/ConstString.h"
#include <map>
#include <vector>
namespace lldb_private {
// x86AssemblyInspectionEngine - a class which will take a buffer of bytes
// of i386/x86_64 instructions and create an UnwindPlan based on those
// assembly instructions.
class x86AssemblyInspectionEngine {
public:
/// default ctor
x86AssemblyInspectionEngine(const lldb_private::ArchSpec &arch);
/// default dtor
~x86AssemblyInspectionEngine();
/// One of the two initialize methods that can be called on this object;
/// they must be called before any of the assembly inspection methods
/// are called. This one should be used if the caller has access to a
/// valid RegisterContext.
void Initialize(lldb::RegisterContextSP &reg_ctx);
/// One of the two initialize methods that can be called on this object;
/// they must be called before any of the assembly inspection methods
/// are called. This one takes a vector of register name and lldb
/// register numbers.
struct lldb_reg_info {
const char *name;
uint32_t lldb_regnum;
lldb_reg_info() : name(nullptr), lldb_regnum(LLDB_INVALID_REGNUM) {}
};
void Initialize(std::vector<lldb_reg_info> &reg_info);
/// Create an UnwindPlan for a "non-call site" stack frame situation.
/// This is usually when this function/method is currently executing, and may
/// be at
/// a location where exception-handling style unwind information (eh_frame,
/// compact unwind info, arm unwind info)
/// are not valid.
/// \p data is a pointer to the instructions for the function
/// \p size is the size of the instruction buffer above
/// \p func_range is the start Address and size of the function, to be
/// included in the UnwindPlan
/// \p unwind_plan is the unwind plan that this method creates
/// \returns true if it was able to create an UnwindPlan; false if not.
bool
GetNonCallSiteUnwindPlanFromAssembly(uint8_t *data, size_t size,
lldb_private::AddressRange &func_range,
lldb_private::UnwindPlan &unwind_plan);
/// Take an existing UnwindPlan, probably from eh_frame which may be missing
/// description
/// of the epilogue instructions, and add the epilogue description to it based
/// on the
/// instructions in the function.
///
/// The \p unwind_plan 's register numbers must be converted into the lldb
/// register numbering
/// scheme OR a RegisterContext must be provided in \p reg_ctx. If the \p
/// unwind_plan
/// register numbers are already in lldb register numbering, \p reg_ctx may be
/// null.
/// \returns true if the \p unwind_plan was updated, false if it was not.
bool AugmentUnwindPlanFromCallSite(uint8_t *data, size_t size,
lldb_private::AddressRange &func_range,
lldb_private::UnwindPlan &unwind_plan,
lldb::RegisterContextSP &reg_ctx);
bool FindFirstNonPrologueInstruction(uint8_t *data, size_t size,
size_t &offset);
private:
bool nonvolatile_reg_p(int machine_regno);
bool push_rbp_pattern_p();
bool push_0_pattern_p();
bool push_imm_pattern_p();
bool mov_rsp_rbp_pattern_p();
bool sub_rsp_pattern_p(int &amount);
bool add_rsp_pattern_p(int &amount);
bool lea_rsp_pattern_p(int &amount);
bool push_reg_p(int &regno);
bool pop_reg_p(int &regno);
bool pop_rbp_pattern_p();
bool leave_pattern_p();
bool call_next_insn_pattern_p();
bool mov_reg_to_local_stack_frame_p(int &regno, int &rbp_offset);
bool ret_pattern_p();
uint32_t extract_4(uint8_t *b);
bool instruction_length(uint8_t *insn, int &length);
bool machine_regno_to_lldb_regno(int machine_regno, uint32_t &lldb_regno);
enum CPU { k_i386, k_x86_64, k_cpu_unspecified };
enum i386_register_numbers {
k_machine_eax = 0,
k_machine_ecx = 1,
k_machine_edx = 2,
k_machine_ebx = 3,
k_machine_esp = 4,
k_machine_ebp = 5,
k_machine_esi = 6,
k_machine_edi = 7,
k_machine_eip = 8
};
enum x86_64_register_numbers {
k_machine_rax = 0,
k_machine_rcx = 1,
k_machine_rdx = 2,
k_machine_rbx = 3,
k_machine_rsp = 4,
k_machine_rbp = 5,
k_machine_rsi = 6,
k_machine_rdi = 7,
k_machine_r8 = 8,
k_machine_r9 = 9,
k_machine_r10 = 10,
k_machine_r11 = 11,
k_machine_r12 = 12,
k_machine_r13 = 13,
k_machine_r14 = 14,
k_machine_r15 = 15,
k_machine_rip = 16
};
enum { kMaxInstructionByteSize = 32 };
uint8_t *m_cur_insn;
uint32_t m_machine_ip_regnum;
uint32_t m_machine_sp_regnum;
uint32_t m_machine_fp_regnum;
uint32_t m_lldb_ip_regnum;
uint32_t m_lldb_sp_regnum;
uint32_t m_lldb_fp_regnum;
typedef std::map<uint32_t, lldb_reg_info> MachineRegnumToNameAndLLDBRegnum;
MachineRegnumToNameAndLLDBRegnum m_reg_map;
lldb_private::ArchSpec m_arch;
CPU m_cpu;
int m_wordsize;
bool m_register_map_initialized;
::LLVMDisasmContextRef m_disasm_context;
DISALLOW_COPY_AND_ASSIGN(x86AssemblyInspectionEngine);
};
} // namespace lldb_private
#endif // liblldb_x86AssemblyInspectionEngine_h_

View File

@ -50,4 +50,5 @@ add_subdirectory(Process)
add_subdirectory(ScriptInterpreter)
add_subdirectory(Symbol)
add_subdirectory(SymbolFile)
add_subdirectory(UnwindAssembly)
add_subdirectory(Utility)

View File

@ -0,0 +1 @@
add_subdirectory(x86)

View File

@ -0,0 +1,3 @@
add_lldb_unittest(UnwindAssemblyx86Tests
Testx86AssemblyInspectionEngine.cpp
)

View File

@ -0,0 +1,281 @@
//===-- Testx86AssemblyInspectionEngine.cpp ---------------------------*- C++
//-*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "gtest/gtest.h"
#include <vector>
#include "Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h"
#include "lldb/Core/Address.h"
#include "lldb/Core/AddressRange.h"
#include "lldb/Core/ArchSpec.h"
#include "lldb/Symbol/UnwindPlan.h"
#include "llvm/Support/TargetSelect.h"
using namespace lldb;
using namespace lldb_private;
class Testx86AssemblyInspectionEngine : public testing::Test {
public:
// static void SetUpTestCase() { }
// static void TearDownTestCase() { }
// virtual void SetUp() override { }
// virtual void TearDown() override { }
protected:
};
// only defining the register names / numbers that the unwinder is actually
// using today
// names should match the constants below. These will be the eRegisterKindLLDB
// register numbers.
const char *x86_64_reg_names[] = {"rax", "rcx", "rdx", "rsp", "rbp", "rsi",
"rdi", "r8", "r9", "r10", "r11", "r12",
"r13", "r14", "r15", "rip"};
enum x86_64_regs {
k_rax = 0,
k_rcx = 1,
k_rdx = 2,
k_rsp = 3,
k_rbp = 4,
k_rsi = 5,
k_rdi = 6,
k_r8 = 7,
k_r9 = 8,
k_r10 = 9,
k_r11 = 10,
k_r12 = 11,
k_r13 = 12,
k_r14 = 13,
k_r15 = 14,
k_rip = 15
};
// names should match the constants below. These will be the eRegisterKindLLDB
// register numbers.
const char *i386_reg_names[] = {"eax", "ecx", "edx", "ebx", "esp",
"ebp", "esi", "edi", "eip"};
enum i386_regs {
k_eax = 0,
k_ecx = 1,
k_edx = 2,
k_ebx = 3,
k_esp = 4,
k_ebp = 5,
k_esi = 6,
k_edi = 7,
k_eip = 8
};
std::unique_ptr<x86AssemblyInspectionEngine> Getx86_64Inspector() {
ArchSpec arch("x86_64-apple-macosx", nullptr);
llvm::InitializeAllTargets();
llvm::InitializeAllAsmPrinters();
llvm::InitializeAllTargetMCs();
llvm::InitializeAllDisassemblers();
std::unique_ptr<x86AssemblyInspectionEngine> engine(
new x86AssemblyInspectionEngine(arch));
std::vector<x86AssemblyInspectionEngine::lldb_reg_info> lldb_regnums;
int i = 0;
for (const auto &name : x86_64_reg_names) {
x86AssemblyInspectionEngine::lldb_reg_info ri;
ri.name = name;
ri.lldb_regnum = i++;
lldb_regnums.push_back(ri);
}
engine->Initialize(lldb_regnums);
return engine;
}
std::unique_ptr<x86AssemblyInspectionEngine> Geti386Inspector() {
ArchSpec arch("i386-apple-macosx", nullptr);
llvm::InitializeAllTargets();
llvm::InitializeAllAsmPrinters();
llvm::InitializeAllTargetMCs();
llvm::InitializeAllDisassemblers();
std::unique_ptr<x86AssemblyInspectionEngine> engine(
new x86AssemblyInspectionEngine(arch));
std::vector<x86AssemblyInspectionEngine::lldb_reg_info> lldb_regnums;
int i = 0;
for (const auto &name : i386_reg_names) {
x86AssemblyInspectionEngine::lldb_reg_info ri;
ri.name = name;
ri.lldb_regnum = i++;
lldb_regnums.push_back(ri);
}
engine->Initialize(lldb_regnums);
return engine;
}
TEST_F(Testx86AssemblyInspectionEngine, TestSimple64bitFrameFunction) {
std::unique_ptr<x86AssemblyInspectionEngine> engine = Getx86_64Inspector();
uint8_t data[] = {
0x55, // offset 0 -- pushq %rbp
0x48, 0x89, 0xe5, // offset 1 -- movq %rsp, %rbp
0x31, 0xc0, // offset 4 -- xorl %eax, %eax
0x5d, // offset 6 -- popq %rbp
0xc3 // offset 7 -- retq
};
AddressRange sample_range(0x1000, sizeof(data));
UnwindPlan unwind_plan(eRegisterKindLLDB);
EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(
data, sizeof(data), sample_range, unwind_plan));
// Expect four unwind rows:
// 0: CFA=rsp +8 => rsp=CFA+0 rip=[CFA-8]
// 1: CFA=rsp+16 => rbp=[CFA-16] rsp=CFA+0 rip=[CFA-8]
// 4: CFA=rbp+16 => rbp=[CFA-16] rsp=CFA+0 rip=[CFA-8]
// 7: CFA=rsp +8 => rsp=CFA+0 rip=[CFA-8]
EXPECT_TRUE(unwind_plan.GetInitialCFARegister() == k_rsp);
EXPECT_TRUE(unwind_plan.GetUnwindPlanValidAtAllInstructions() ==
eLazyBoolYes);
EXPECT_TRUE(unwind_plan.GetSourcedFromCompiler() == eLazyBoolNo);
UnwindPlan::Row::RegisterLocation regloc;
// 0: CFA=rsp +8 => rsp=CFA+0 rip=[CFA-8]
UnwindPlan::RowSP row_sp = unwind_plan.GetRowForFunctionOffset(0);
EXPECT_TRUE(row_sp->GetOffset() == 0);
EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp);
EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
EXPECT_TRUE(row_sp->GetCFAValue().GetOffset() == 8);
EXPECT_TRUE(row_sp->GetRegisterInfo(k_rip, regloc));
EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
EXPECT_TRUE(regloc.GetOffset() == -8);
// 1: CFA=rsp+16 => rbp=[CFA-16] rsp=CFA+0 rip=[CFA-8]
row_sp = unwind_plan.GetRowForFunctionOffset(1);
EXPECT_TRUE(row_sp->GetOffset() == 1);
EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp);
EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
EXPECT_TRUE(row_sp->GetCFAValue().GetOffset() == 16);
EXPECT_TRUE(row_sp->GetRegisterInfo(k_rip, regloc));
EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
EXPECT_TRUE(regloc.GetOffset() == -8);
// 4: CFA=rbp+16 => rbp=[CFA-16] rsp=CFA+0 rip=[CFA-8]
row_sp = unwind_plan.GetRowForFunctionOffset(4);
EXPECT_TRUE(row_sp->GetOffset() == 4);
EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rbp);
EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
EXPECT_TRUE(row_sp->GetCFAValue().GetOffset() == 16);
EXPECT_TRUE(row_sp->GetRegisterInfo(k_rip, regloc));
EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
EXPECT_TRUE(regloc.GetOffset() == -8);
// 7: CFA=rsp +8 => rsp=CFA+0 rip=[CFA-8]
row_sp = unwind_plan.GetRowForFunctionOffset(7);
EXPECT_TRUE(row_sp->GetOffset() == 7);
EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_rsp);
EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
EXPECT_TRUE(row_sp->GetCFAValue().GetOffset() == 8);
EXPECT_TRUE(row_sp->GetRegisterInfo(k_rip, regloc));
EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
EXPECT_TRUE(regloc.GetOffset() == -8);
}
TEST_F(Testx86AssemblyInspectionEngine, TestSimple32bitFrameFunction) {
std::unique_ptr<x86AssemblyInspectionEngine> engine = Geti386Inspector();
uint8_t data[] = {
0x55, // offset 0 -- pushl %ebp
0x89, 0xe5, // offset 1 -- movl %esp, %ebp
0x31, 0xc0, // offset 3 -- xorl %eax, %eax
0x5d, // offset 5 -- popl %ebp
0xc3 // offset 6 -- retl
};
AddressRange sample_range(0x1000, sizeof(data));
UnwindPlan unwind_plan(eRegisterKindLLDB);
EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(
data, sizeof(data), sample_range, unwind_plan));
// Expect four unwind rows:
// 0: CFA=esp +4 => esp=CFA+0 eip=[CFA-4]
// 1: CFA=esp +8 => ebp=[CFA-8] esp=CFA+0 eip=[CFA-4]
// 3: CFA=ebp +8 => ebp=[CFA-8] esp=CFA+0 eip=[CFA-4]
// 6: CFA=esp +4 => esp=CFA+0 eip=[CFA-4]
EXPECT_TRUE(unwind_plan.GetInitialCFARegister() == k_esp);
EXPECT_TRUE(unwind_plan.GetUnwindPlanValidAtAllInstructions() ==
eLazyBoolYes);
EXPECT_TRUE(unwind_plan.GetSourcedFromCompiler() == eLazyBoolNo);
UnwindPlan::Row::RegisterLocation regloc;
// offset 0 -- pushl %ebp
UnwindPlan::RowSP row_sp = unwind_plan.GetRowForFunctionOffset(0);
EXPECT_TRUE(row_sp->GetOffset() == 0);
EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_esp);
EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
EXPECT_TRUE(row_sp->GetCFAValue().GetOffset() == 4);
EXPECT_TRUE(row_sp->GetRegisterInfo(k_eip, regloc));
EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
EXPECT_TRUE(regloc.GetOffset() == -4);
// 1: CFA=esp +8 => ebp=[CFA-8] esp=CFA+0 eip=[CFA-4]
row_sp = unwind_plan.GetRowForFunctionOffset(1);
EXPECT_TRUE(row_sp->GetOffset() == 1);
EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_esp);
EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
EXPECT_TRUE(row_sp->GetCFAValue().GetOffset() == 8);
EXPECT_TRUE(row_sp->GetRegisterInfo(k_eip, regloc));
EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
EXPECT_TRUE(regloc.GetOffset() == -4);
// 3: CFA=ebp +8 => ebp=[CFA-8] esp=CFA+0 eip=[CFA-4]
row_sp = unwind_plan.GetRowForFunctionOffset(3);
EXPECT_TRUE(row_sp->GetOffset() == 3);
EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_ebp);
EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
EXPECT_TRUE(row_sp->GetCFAValue().GetOffset() == 8);
EXPECT_TRUE(row_sp->GetRegisterInfo(k_eip, regloc));
EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
EXPECT_TRUE(regloc.GetOffset() == -4);
// 6: CFA=esp +4 => esp=CFA+0 eip=[CFA-4]
row_sp = unwind_plan.GetRowForFunctionOffset(6);
EXPECT_TRUE(row_sp->GetOffset() == 6);
EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == k_esp);
EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
EXPECT_TRUE(row_sp->GetCFAValue().GetOffset() == 4);
EXPECT_TRUE(row_sp->GetRegisterInfo(k_eip, regloc));
EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
EXPECT_TRUE(regloc.GetOffset() == -4);
}