summaryrefslogtreecommitdiffstats
path: root/lldb/source/Plugins/ABI
diff options
context:
space:
mode:
authorGreg Clayton <gclayton@apple.com>2011-05-11 18:39:18 +0000
committerGreg Clayton <gclayton@apple.com>2011-05-11 18:39:18 +0000
commit31f1d2f53593a7e5449164962edfc0505a669128 (patch)
treed79fb8e40b234c30398c18edd67b97c6aee5df27 /lldb/source/Plugins/ABI
parent31a0b5e2f005b75d0606e3283a2853392c796bb9 (diff)
downloadbcm5719-llvm-31f1d2f53593a7e5449164962edfc0505a669128.tar.gz
bcm5719-llvm-31f1d2f53593a7e5449164962edfc0505a669128.zip
Moved all code from ArchDefaultUnwindPlan and ArchVolatileRegs into their
respective ABI plugins as they were plug-ins that supplied ABI specfic info. Also hookep up the UnwindAssemblyInstEmulation so that it can generate the unwind plans for ARM. Changed the way ABI plug-ins are handed out when you get an instance from the plug-in manager. They used to return pointers that would be mananged individually by each client that requested them, but now they are handed out as shared pointers since there is no state in the ABI objects, they can be shared. llvm-svn: 131193
Diffstat (limited to 'lldb/source/Plugins/ABI')
-rw-r--r--lldb/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp807
-rw-r--r--lldb/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h95
-rw-r--r--lldb/source/Plugins/ABI/MacOSX-arm/Makefile14
-rw-r--r--lldb/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp152
-rw-r--r--lldb/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h246
-rw-r--r--lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp151
-rw-r--r--lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h178
7 files changed, 1561 insertions, 82 deletions
diff --git a/lldb/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp b/lldb/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp
new file mode 100644
index 00000000000..0f9bab1fcec
--- /dev/null
+++ b/lldb/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp
@@ -0,0 +1,807 @@
+//===-- ABIMacOSX_arm.cpp --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ABIMacOSX_arm.h"
+
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Scalar.h"
+#include "lldb/Core/Value.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/UnwindPlan.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+
+#include "llvm/ADT/Triple.h"
+
+#include "Utility/ARM_DWARF_Registers.h"
+
+#include <vector>
+
+using namespace lldb;
+using namespace lldb_private;
+
+static const char *pluginName = "ABIMacOSX_arm";
+static const char *pluginDesc = "Mac OS X ABI for arm targets";
+static const char *pluginShort = "abi.macosx-arm";
+
+size_t
+ABIMacOSX_arm::GetRedZoneSize () const
+{
+ return 0;
+}
+
+//------------------------------------------------------------------
+// Static Functions
+//------------------------------------------------------------------
+ABISP
+ABIMacOSX_arm::CreateInstance (const ArchSpec &arch)
+{
+ static ABISP g_abi_sp;
+ const llvm::Triple::ArchType arch_type = arch.GetTriple().getArch();
+ if ((arch_type == llvm::Triple::arm) ||
+ (arch_type == llvm::Triple::thumb))
+ {
+ if (!g_abi_sp)
+ g_abi_sp.reset (new ABIMacOSX_arm);
+ return g_abi_sp;
+ }
+ return ABISP();
+}
+
+bool
+ABIMacOSX_arm::PrepareTrivialCall (Thread &thread,
+ addr_t sp,
+ addr_t functionAddress,
+ addr_t returnAddress,
+ addr_t arg,
+ addr_t *this_arg,
+ addr_t *cmd_arg) const
+{
+// RegisterContext *reg_ctx = thread.GetRegisterContext().get();
+// if (!reg_ctx)
+// return false;
+//#define CHAIN_EBP
+//
+//#ifndef CHAIN_EBP
+// uint32_t ebpID = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP);
+//#endif
+// uint32_t eipID = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
+// uint32_t espID = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
+//
+// // Make room for the argument(s) on the stack
+//
+// if (this_arg && cmd_arg)
+// sp -= 12;
+// else if (this_arg)
+// sp -= 8;
+// else
+// sp -= 4;
+//
+// // Align the SP
+//
+// sp &= ~(0xfull); // 16-byte alignment
+//
+// // Write the argument on the stack
+//
+// Error error;
+//
+// if (this_arg && cmd_arg)
+// {
+// uint32_t cmd_argU32 = *cmd_arg & 0xffffffffull;
+// uint32_t this_argU32 = *this_arg & 0xffffffffull;
+// uint32_t argU32 = arg & 0xffffffffull;
+//
+// if (thread.GetProcess().WriteMemory(sp, &this_argU32, sizeof(this_argU32), error) != sizeof(this_argU32))
+// return false;
+// if (thread.GetProcess().WriteMemory(sp + 4, &cmd_argU32, sizeof(cmd_argU32), error) != sizeof(cmd_argU32))
+// return false;
+// if (thread.GetProcess().WriteMemory(sp + 8, &argU32, sizeof(argU32), error) != sizeof(argU32))
+// return false;
+// }
+// else if (this_arg)
+// {
+// uint32_t this_argU32 = *this_arg & 0xffffffffull;
+// uint32_t argU32 = arg & 0xffffffffull;
+//
+// if (thread.GetProcess().WriteMemory(sp, &this_argU32, sizeof(this_argU32), error) != sizeof(this_argU32))
+// return false;
+// if (thread.GetProcess().WriteMemory(sp + 4, &argU32, sizeof(argU32), error) != sizeof(argU32))
+// return false;
+// }
+// else
+// {
+// uint32_t argU32 = arg & 0xffffffffull;
+//
+// if (thread.GetProcess().WriteMemory (sp, &argU32, sizeof(argU32), error) != sizeof(argU32))
+// return false;
+// }
+//
+// // The return address is pushed onto the stack.
+//
+// sp -= 4;
+// uint32_t returnAddressU32 = returnAddress;
+// if (thread.GetProcess().WriteMemory (sp, &returnAddressU32, sizeof(returnAddressU32), error) != sizeof(returnAddressU32))
+// return false;
+//
+// // %esp is set to the actual stack value.
+//
+// if (!reg_ctx->WriteRegisterFromUnsigned(espID, sp))
+// return false;
+//
+//#ifndef CHAIN_EBP
+// // %ebp is set to a fake value, in our case 0x0x00000000
+//
+// if (!reg_ctx->WriteRegisterFromUnsigned(ebpID, 0x00000000))
+// return false;
+//#endif
+//
+// // %eip is set to the address of the called function.
+//
+// if (!reg_ctx->WriteRegisterFromUnsigned(eipID, functionAddress))
+// return false;
+//
+// return true;
+ return false;
+}
+
+bool
+ABIMacOSX_arm::PrepareNormalCall (Thread &thread,
+ addr_t sp,
+ addr_t functionAddress,
+ addr_t returnAddress,
+ ValueList &args) const
+{
+// RegisterContext *reg_ctx = thread.GetRegisterContext().get();
+// if (!reg_ctx)
+// return false;
+// Error error;
+// uint32_t ebpID = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP);
+// uint32_t eipID = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
+// uint32_t espID = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
+//
+// // Do the argument layout
+//
+// std::vector <uint32_t> argLayout; // 4-byte chunks, as discussed in the ABI Function Call Guide
+//
+// size_t numArgs = args.GetSize();
+// size_t index;
+//
+// for (index = 0; index < numArgs; ++index)
+// {
+// Value *val = args.GetValueAtIndex(index);
+//
+// if (!val)
+// return false;
+//
+// switch (val->GetValueType())
+// {
+// case Value::eValueTypeScalar:
+// {
+// Scalar &scalar = val->GetScalar();
+// switch (scalar.GetType())
+// {
+// case Scalar::e_void:
+// default:
+// return false;
+// case Scalar::e_sint:
+// case Scalar::e_uint:
+// case Scalar::e_slong:
+// case Scalar::e_ulong:
+// case Scalar::e_slonglong:
+// case Scalar::e_ulonglong:
+// {
+// uint64_t data = scalar.ULongLong();
+//
+// switch (scalar.GetByteSize())
+// {
+// default:
+// return false;
+// case 1:
+// argLayout.push_back((uint32_t)(data & 0xffull));
+// break;
+// case 2:
+// argLayout.push_back((uint32_t)(data & 0xffffull));
+// break;
+// case 4:
+// argLayout.push_back((uint32_t)(data & 0xffffffffull));
+// break;
+// case 8:
+// argLayout.push_back((uint32_t)(data & 0xffffffffull));
+// argLayout.push_back((uint32_t)(data >> 32));
+// break;
+// }
+// }
+// break;
+// case Scalar::e_float:
+// {
+// float data = scalar.Float();
+// uint32_t dataRaw = *((uint32_t*)(&data));
+// argLayout.push_back(dataRaw);
+// }
+// break;
+// case Scalar::e_double:
+// {
+// double data = scalar.Double();
+// uint32_t *dataRaw = ((uint32_t*)(&data));
+// argLayout.push_back(dataRaw[0]);
+// argLayout.push_back(dataRaw[1]);
+// }
+// break;
+// case Scalar::e_long_double:
+// {
+// long double data = scalar.Double();
+// uint32_t *dataRaw = ((uint32_t*)(&data));
+// while ((argLayout.size() * 4) & 0xf)
+// argLayout.push_back(0);
+// argLayout.push_back(dataRaw[0]);
+// argLayout.push_back(dataRaw[1]);
+// argLayout.push_back(dataRaw[2]);
+// argLayout.push_back(dataRaw[3]);
+// }
+// break;
+// }
+// }
+// break;
+// case Value::eValueTypeHostAddress:
+// switch (val->GetContextType())
+// {
+// default:
+// return false;
+// case Value::eContextTypeClangType:
+// {
+// void *val_type = val->GetClangType();
+// uint32_t cstr_length;
+//
+// if (ClangASTContext::IsCStringType (val_type, cstr_length))
+// {
+// const char *cstr = (const char*)val->GetScalar().ULongLong();
+// cstr_length = strlen(cstr);
+//
+// // Push the string onto the stack immediately.
+//
+// sp -= (cstr_length + 1);
+//
+// if (thread.GetProcess().WriteMemory(sp, cstr, cstr_length + 1, error) != (cstr_length + 1))
+// return false;
+//
+// // Put the address of the string into the argument array.
+//
+// argLayout.push_back((uint32_t)(sp & 0xffffffff));
+// }
+// else
+// {
+// return false;
+// }
+// }
+// break;
+// }
+// break;
+// case Value::eValueTypeFileAddress:
+// case Value::eValueTypeLoadAddress:
+// default:
+// return false;
+// }
+// }
+//
+// // Make room for the arguments on the stack
+//
+// sp -= 4 * argLayout.size();
+//
+// // Align the SP
+//
+// sp &= ~(0xfull); // 16-byte alignment
+//
+// // Write the arguments on the stack
+//
+// size_t numChunks = argLayout.size();
+//
+// for (index = 0; index < numChunks; ++index)
+// if (thread.GetProcess().WriteMemory(sp + (index * 4), &argLayout[index], sizeof(uint32_t), error) != sizeof(uint32_t))
+// return false;
+//
+// // The return address is pushed onto the stack.
+//
+// sp -= 4;
+// uint32_t returnAddressU32 = returnAddress;
+// if (thread.GetProcess().WriteMemory (sp, &returnAddressU32, sizeof(returnAddressU32), error) != sizeof(returnAddressU32))
+// return false;
+//
+// // %esp is set to the actual stack value.
+//
+// if (!reg_ctx->WriteRegisterFromUnsigned(espID, sp))
+// return false;
+//
+// // %ebp is set to a fake value, in our case 0x0x00000000
+//
+// if (!reg_ctx->WriteRegisterFromUnsigned(ebpID, 0x00000000))
+// return false;
+//
+// // %eip is set to the address of the called function.
+//
+// if (!reg_ctx->WriteRegisterFromUnsigned(eipID, functionAddress))
+// return false;
+//
+// return true;
+ return false;
+}
+
+static bool
+ReadIntegerArgument (Scalar &scalar,
+ unsigned int bit_width,
+ bool is_signed,
+ Process &process,
+ addr_t &current_stack_argument)
+{
+// if (bit_width > 64)
+// return false; // Scalar can't hold large integer arguments
+//
+// uint64_t arg_contents;
+// uint32_t read_data;
+// Error error;
+//
+// if (bit_width > 32)
+// {
+// if (process.ReadMemory(current_stack_argument, &read_data, sizeof(read_data), error) != sizeof(read_data))
+// return false;
+//
+// arg_contents = read_data;
+//
+// if (process.ReadMemory(current_stack_argument + 4, &read_data, sizeof(read_data), error) != sizeof(read_data))
+// return false;
+//
+// arg_contents |= ((uint64_t)read_data) << 32;
+//
+// current_stack_argument += 8;
+// }
+// else {
+// if (process.ReadMemory(current_stack_argument, &read_data, sizeof(read_data), error) != sizeof(read_data))
+// return false;
+//
+// arg_contents = read_data;
+//
+// current_stack_argument += 4;
+// }
+//
+// if (is_signed)
+// {
+// switch (bit_width)
+// {
+// default:
+// return false;
+// case 8:
+// scalar = (int8_t)(arg_contents & 0xff);
+// break;
+// case 16:
+// scalar = (int16_t)(arg_contents & 0xffff);
+// break;
+// case 32:
+// scalar = (int32_t)(arg_contents & 0xffffffff);
+// break;
+// case 64:
+// scalar = (int64_t)arg_contents;
+// break;
+// }
+// }
+// else
+// {
+// switch (bit_width)
+// {
+// default:
+// return false;
+// case 8:
+// scalar = (uint8_t)(arg_contents & 0xff);
+// break;
+// case 16:
+// scalar = (uint16_t)(arg_contents & 0xffff);
+// break;
+// case 32:
+// scalar = (uint32_t)(arg_contents & 0xffffffff);
+// break;
+// case 64:
+// scalar = (uint64_t)arg_contents;
+// break;
+// }
+// }
+//
+// return true;
+ return false;
+}
+
+bool
+ABIMacOSX_arm::GetArgumentValues (Thread &thread,
+ ValueList &values) const
+{
+// unsigned int num_values = values.GetSize();
+// unsigned int value_index;
+//
+// // Extract the Clang AST context from the PC so that we can figure out type
+// // sizes
+//
+// clang::ASTContext *ast_context = thread.CalculateTarget()->GetScratchClangASTContext()->getASTContext();
+//
+// // Get the pointer to the first stack argument so we have a place to start
+// // when reading data
+//
+// RegisterContext *reg_ctx = thread.GetRegisterContext().get();
+//
+// if (!reg_ctx)
+// return false;
+//
+// addr_t sp = reg_ctx->GetSP(0);
+//
+// if (!sp)
+// return false;
+//
+// addr_t current_stack_argument = sp + 4; // jump over return address
+//
+// for (value_index = 0;
+// value_index < num_values;
+// ++value_index)
+// {
+// Value *value = values.GetValueAtIndex(value_index);
+//
+// if (!value)
+// return false;
+//
+// // We currently only support extracting values with Clang QualTypes.
+// // Do we care about others?
+// switch (value->GetContextType())
+// {
+// default:
+// return false;
+// case Value::eContextTypeClangType:
+// {
+// void *value_type = value->GetClangType();
+// bool is_signed;
+//
+// if (ClangASTContext::IsIntegerType (value_type, is_signed))
+// {
+// size_t bit_width = ClangASTType::GetClangTypeBitWidth(ast_context, value_type);
+//
+// ReadIntegerArgument(value->GetScalar(),
+// bit_width,
+// is_signed,
+// thread.GetProcess(),
+// current_stack_argument);
+// }
+// else if (ClangASTContext::IsPointerType (value_type))
+// {
+// ReadIntegerArgument(value->GetScalar(),
+// 32,
+// false,
+// thread.GetProcess(),
+// current_stack_argument);
+// }
+// }
+// break;
+// }
+// }
+//
+// return true;
+ return false;
+}
+
+bool
+ABIMacOSX_arm::GetReturnValue (Thread &thread,
+ Value &value) const
+{
+// switch (value.GetContextType())
+// {
+// default:
+// return false;
+// case Value::eContextTypeClangType:
+// {
+// // Extract the Clang AST context from the PC so that we can figure out type
+// // sizes
+//
+// clang::ASTContext *ast_context = thread.CalculateTarget()->GetScratchClangASTContext()->getASTContext();
+//
+// // Get the pointer to the first stack argument so we have a place to start
+// // when reading data
+//
+// RegisterContext *reg_ctx = thread.GetRegisterContext().get();
+//
+// void *value_type = value.GetClangType();
+// bool is_signed;
+//
+// if (ClangASTContext::IsIntegerType (value_type, is_signed))
+// {
+// size_t bit_width = ClangASTType::GetClangTypeBitWidth(ast_context, value_type);
+//
+// unsigned eax_id = reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB];
+// unsigned edx_id = reg_ctx->GetRegisterInfoByName("edx", 0)->kinds[eRegisterKindLLDB];
+//
+// switch (bit_width)
+// {
+// default:
+// case 128:
+// // Scalar can't hold 128-bit literals, so we don't handle this
+// return false;
+// case 64:
+// uint64_t raw_value;
+// raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff;
+// raw_value |= (thread.GetRegisterContext()->ReadRegisterAsUnsigned(edx_id, 0) & 0xffffffff) << 32;
+// if (is_signed)
+// value.GetScalar() = (int64_t)raw_value;
+// else
+// value.GetScalar() = (uint64_t)raw_value;
+// break;
+// case 32:
+// if (is_signed)
+// value.GetScalar() = (int32_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff);
+// else
+// value.GetScalar() = (uint32_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff);
+// break;
+// case 16:
+// if (is_signed)
+// value.GetScalar() = (int16_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffff);
+// else
+// value.GetScalar() = (uint16_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffff);
+// break;
+// case 8:
+// if (is_signed)
+// value.GetScalar() = (int8_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xff);
+// else
+// value.GetScalar() = (uint8_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xff);
+// break;
+// }
+// }
+// else if (ClangASTContext::IsPointerType (value_type))
+// {
+// unsigned eax_id = reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB];
+// uint32_t ptr = thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff;
+// value.GetScalar() = ptr;
+// }
+// else
+// {
+// // not handled yet
+// return false;
+// }
+// }
+// break;
+// }
+//
+// return true;
+ return false;
+}
+
+bool
+ABIMacOSX_arm::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)
+{
+ uint32_t reg_kind = unwind_plan.GetRegisterKind();
+ uint32_t lr_reg_num = LLDB_INVALID_REGNUM;
+ uint32_t sp_reg_num = LLDB_INVALID_REGNUM;
+ uint32_t pc_reg_num = LLDB_INVALID_REGNUM;
+
+ switch (reg_kind)
+ {
+ case eRegisterKindDWARF:
+ case eRegisterKindGCC:
+ lr_reg_num = dwarf_lr;
+ sp_reg_num = dwarf_sp;
+ pc_reg_num = dwarf_pc;
+ break;
+
+ case eRegisterKindGeneric:
+ lr_reg_num = LLDB_REGNUM_GENERIC_RA;
+ sp_reg_num = LLDB_REGNUM_GENERIC_SP;
+ pc_reg_num = LLDB_REGNUM_GENERIC_PC;
+ break;
+ }
+
+ if (lr_reg_num == LLDB_INVALID_REGNUM ||
+ sp_reg_num == LLDB_INVALID_REGNUM ||
+ pc_reg_num == LLDB_INVALID_REGNUM)
+ return false;
+
+ unwind_plan.Clear();
+ unwind_plan.SetRegisterKind (eRegisterKindDWARF);
+
+ UnwindPlan::Row row;
+
+ // Our previous Call Frame Address is the stack pointer
+ row.SetCFARegister (sp_reg_num);
+
+ // Our previous PC is in the LR
+ row.SetRegisterLocationToRegister(pc_reg_num, lr_reg_num, true);
+ unwind_plan.AppendRow (row);
+
+ // All other registers are the same.
+
+ unwind_plan.SetSourceName (pluginName);
+ return true;
+}
+
+bool
+ABIMacOSX_arm::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)
+{
+ uint32_t reg_kind = unwind_plan.GetRegisterKind();
+ uint32_t fp_reg_num = LLDB_INVALID_REGNUM;
+ uint32_t sp_reg_num = LLDB_INVALID_REGNUM;
+ uint32_t pc_reg_num = LLDB_INVALID_REGNUM;
+
+ switch (reg_kind)
+ {
+ case eRegisterKindDWARF:
+ case eRegisterKindGCC:
+ fp_reg_num = dwarf_r7; // apple uses r7 for all frames. Normal arm uses r11
+ sp_reg_num = dwarf_sp;
+ pc_reg_num = dwarf_pc;
+ break;
+
+ case eRegisterKindGeneric:
+ fp_reg_num = LLDB_REGNUM_GENERIC_FP;
+ sp_reg_num = LLDB_REGNUM_GENERIC_SP;
+ pc_reg_num = LLDB_REGNUM_GENERIC_PC;
+ break;
+ }
+
+ if (fp_reg_num == LLDB_INVALID_REGNUM ||
+ sp_reg_num == LLDB_INVALID_REGNUM ||
+ pc_reg_num == LLDB_INVALID_REGNUM)
+ return false;
+
+ UnwindPlan::Row row;
+ const int32_t ptr_size = 8;
+
+ unwind_plan.SetRegisterKind (eRegisterKindGeneric);
+ row.SetCFARegister (fp_reg_num);
+ row.SetCFAOffset (2 * ptr_size);
+ row.SetOffset (0);
+
+ row.SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true);
+ row.SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true);
+
+ unwind_plan.AppendRow (row);
+ unwind_plan.SetSourceName ("arm-apple-darwin default unwind plan");
+ return true;
+}
+
+bool
+ABIMacOSX_arm::RegisterIsVolatile (const RegisterInfo *reg_info)
+{
+ if (reg_info)
+ {
+ // Volatile registers include: ebx, ebp, esi, edi, esp, eip
+ const char *name = reg_info->name;
+ if (name[0] == 'r')
+ {
+ switch (name[1])
+ {
+ case '0': return name[2] == '\0'; // r0
+ case '1':
+ switch (name[2])
+ {
+ case '\0':
+ return true; // r1
+ case '2':
+ case '3':
+ return name[2] == '\0'; // r12 - r13
+ default:
+ break;
+ }
+ break;
+
+ case '2': return name[2] == '\0'; // r2
+ case '3': return name[2] == '\0'; // r3
+ case '9': return name[2] == '\0'; // r9 (apple-darwin only...)
+
+ break;
+ }
+ }
+ else if (name[0] == 'd')
+ {
+ switch (name[1])
+ {
+ case '0':
+ return name[2] == '\0'; // d0
+
+ case '1':
+ switch (name[2])
+ {
+ case '\0':
+ return true; // d1;
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ return name[3] == '\0'; // d16 - d19
+ default:
+ break;
+ }
+ break;
+
+ case '2':
+ switch (name[2])
+ {
+ case '\0':
+ return true; // d2;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ return name[3] == '\0'; // d20 - d29
+ default:
+ break;
+ }
+ break;
+
+ case '3':
+ switch (name[2])
+ {
+ case '\0':
+ return true; // d3;
+ case '0':
+ case '1':
+ return name[3] == '\0'; // d30 - d31
+ default:
+ break;
+ }
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ return name[2] == '\0'; // d4 - d7
+
+ default:
+ break;
+ }
+ }
+ else if (name[0] == 's' && name[1] == 'p' && name[2] == '\0')
+ return true;
+ }
+ return false;
+}
+
+void
+ABIMacOSX_arm::Initialize()
+{
+ PluginManager::RegisterPlugin (pluginName,
+ pluginDesc,
+ CreateInstance);
+}
+
+void
+ABIMacOSX_arm::Terminate()
+{
+ PluginManager::UnregisterPlugin (CreateInstance);
+}
+
+//------------------------------------------------------------------
+// PluginInterface protocol
+//------------------------------------------------------------------
+const char *
+ABIMacOSX_arm::GetPluginName()
+{
+ return pluginName;
+}
+
+const char *
+ABIMacOSX_arm::GetShortPluginName()
+{
+ return pluginShort;
+}
+
+uint32_t
+ABIMacOSX_arm::GetPluginVersion()
+{
+ return 1;
+}
+
diff --git a/lldb/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h b/lldb/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h
new file mode 100644
index 00000000000..d1d5dc4c4bc
--- /dev/null
+++ b/lldb/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h
@@ -0,0 +1,95 @@
+//===-- ABIMacOSX_arm.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_ABIMacOSX_arm_h_
+#define liblldb_ABIMacOSX_arm_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Target/ABI.h"
+
+class ABIMacOSX_arm : public lldb_private::ABI
+{
+public:
+ ~ABIMacOSX_arm() { }
+
+ virtual size_t
+ GetRedZoneSize () const;
+
+ virtual bool
+ PrepareTrivialCall (lldb_private::Thread &thread,
+ lldb::addr_t sp,
+ lldb::addr_t functionAddress,
+ lldb::addr_t returnAddress,
+ lldb::addr_t arg,
+ lldb::addr_t *this_arg,
+ lldb::addr_t *cmd_arg) const;
+
+ virtual bool
+ PrepareNormalCall (lldb_private::Thread &thread,
+ lldb::addr_t sp,
+ lldb::addr_t functionAddress,
+ lldb::addr_t returnAddress,
+ lldb_private::ValueList &args) const;
+
+ virtual bool
+ GetArgumentValues (lldb_private::Thread &thread,
+ lldb_private::ValueList &values) const;
+
+ virtual bool
+ GetReturnValue (lldb_private::Thread &thread,
+ lldb_private::Value &value) const;
+
+ virtual bool
+ CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan);
+
+ virtual bool
+ CreateDefaultUnwindPlan (lldb_private::UnwindPlan &unwind_plan);
+
+ virtual bool
+ RegisterIsVolatile (const lldb_private::RegisterInfo *reg_info);
+
+
+ //------------------------------------------------------------------
+ // Static Functions
+ //------------------------------------------------------------------
+ static void
+ Initialize();
+
+ static void
+ Terminate();
+
+ static lldb::ABISP
+ CreateInstance (const lldb_private::ArchSpec &arch);
+
+ //------------------------------------------------------------------
+ // PluginInterface protocol
+ //------------------------------------------------------------------
+ virtual const char *
+ GetPluginName();
+
+ virtual const char *
+ GetShortPluginName();
+
+ virtual uint32_t
+ GetPluginVersion();
+
+protected:
+private:
+ ABIMacOSX_arm() :
+ lldb_private::ABI()
+ {
+ // Call CreateInstance instead.
+ }
+};
+
+#endif // liblldb_ABIMacOSX_arm_h_
diff --git a/lldb/source/Plugins/ABI/MacOSX-arm/Makefile b/lldb/source/Plugins/ABI/MacOSX-arm/Makefile
new file mode 100644
index 00000000000..18073266d34
--- /dev/null
+++ b/lldb/source/Plugins/ABI/MacOSX-arm/Makefile
@@ -0,0 +1,14 @@
+##===- source/Plugins/ABI/MacOSX-arm/Makefile ------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===--------------------------------------------------------------------===##
+
+LLDB_LEVEL := ../../../..
+LIBRARYNAME := lldbPluginABIMacOSX_arm
+BUILD_ARCHIVE = 1
+
+include $(LLDB_LEVEL)/Makefile
diff --git a/lldb/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp b/lldb/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp
index a65a2efa78f..8c9df142890 100644
--- a/lldb/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp
+++ b/lldb/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp
@@ -15,6 +15,7 @@
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Scalar.h"
#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/UnwindPlan.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/Target.h"
@@ -40,13 +41,17 @@ ABIMacOSX_i386::GetRedZoneSize () const
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
-lldb_private::ABI *
+ABISP
ABIMacOSX_i386::CreateInstance (const ArchSpec &arch)
{
+ static ABISP g_abi_sp;
if (arch.GetTriple().getArch() == llvm::Triple::x86)
- return new ABIMacOSX_i386;
-
- return NULL;
+ {
+ if (!g_abi_sp)
+ g_abi_sp.reset (new ABIMacOSX_i386);
+ return g_abi_sp;
+ }
+ return ABISP();
}
bool
@@ -560,6 +565,145 @@ ABIMacOSX_i386::GetReturnValue (Thread &thread,
return true;
}
+bool
+ABIMacOSX_i386::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)
+{
+ uint32_t reg_kind = unwind_plan.GetRegisterKind();
+ uint32_t sp_reg_num = LLDB_INVALID_REGNUM;
+ uint32_t pc_reg_num = LLDB_INVALID_REGNUM;
+
+ switch (reg_kind)
+ {
+ case eRegisterKindDWARF:
+ sp_reg_num = dwarf_esp;
+ pc_reg_num = dwarf_eip;
+ break;
+
+ case eRegisterKindGCC:
+ sp_reg_num = gcc_esp;
+ pc_reg_num = gcc_eip;
+ break;
+
+ case eRegisterKindGDB:
+ sp_reg_num = gdb_esp;
+ pc_reg_num = gdb_eip;
+ break;
+
+ case eRegisterKindGeneric:
+ sp_reg_num = LLDB_REGNUM_GENERIC_SP;
+ pc_reg_num = LLDB_REGNUM_GENERIC_PC;
+ break;
+ }
+
+ if (sp_reg_num == LLDB_INVALID_REGNUM ||
+ pc_reg_num == LLDB_INVALID_REGNUM)
+ return false;
+
+ UnwindPlan::Row row;
+ row.SetCFARegister (sp_reg_num);
+ row.SetCFAOffset (4);
+ row.SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, -4, false);
+ unwind_plan.AppendRow (row);
+ unwind_plan.SetSourceName (pluginName);
+ return true;
+}
+
+bool
+ABIMacOSX_i386::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)
+{
+ uint32_t reg_kind = unwind_plan.GetRegisterKind();
+ uint32_t fp_reg_num = LLDB_INVALID_REGNUM;
+ uint32_t sp_reg_num = LLDB_INVALID_REGNUM;
+ uint32_t pc_reg_num = LLDB_INVALID_REGNUM;
+
+ switch (reg_kind)
+ {
+ case eRegisterKindDWARF:
+ fp_reg_num = dwarf_ebp;
+ sp_reg_num = dwarf_esp;
+ pc_reg_num = dwarf_eip;
+ break;
+
+ case eRegisterKindGCC:
+ fp_reg_num = gcc_ebp;
+ sp_reg_num = gcc_esp;
+ pc_reg_num = gcc_eip;
+ break;
+
+ case eRegisterKindGDB:
+ fp_reg_num = gdb_ebp;
+ sp_reg_num = gdb_esp;
+ pc_reg_num = gdb_eip;
+ break;
+
+ case eRegisterKindGeneric:
+ fp_reg_num = LLDB_REGNUM_GENERIC_FP;
+ sp_reg_num = LLDB_REGNUM_GENERIC_SP;
+ pc_reg_num = LLDB_REGNUM_GENERIC_PC;
+ break;
+ }
+
+ if (fp_reg_num == LLDB_INVALID_REGNUM ||
+ sp_reg_num == LLDB_INVALID_REGNUM ||
+ pc_reg_num == LLDB_INVALID_REGNUM)
+ return false;
+
+ UnwindPlan::Row row;
+ const int32_t ptr_size = 4;
+
+ unwind_plan.SetRegisterKind (eRegisterKindGeneric);
+ row.SetCFARegister (fp_reg_num);
+ row.SetCFAOffset (2 * ptr_size);
+ row.SetOffset (0);
+
+ row.SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true);
+ row.SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true);
+ row.SetRegisterLocationToAtCFAPlusOffset(sp_reg_num, ptr_size * 0, true);
+
+ unwind_plan.AppendRow (row);
+ unwind_plan.SetSourceName ("i386 default unwind plan");
+ return true;
+}
+
+bool
+ABIMacOSX_i386::RegisterIsVolatile (const RegisterInfo *reg_info)
+{
+ return RegisterIsCalleeSaved (reg_info);
+}
+
+bool
+ABIMacOSX_i386::RegisterIsCalleeSaved (const RegisterInfo *reg_info)
+{
+ if (reg_info)
+ {
+ // Volatile registers include: ebx, ebp, esi, edi, esp, eip
+ const char *name = reg_info->name;
+ if (name[0] == 'e')
+ {
+ switch (name[1])
+ {
+ case 'b':
+ if (name[2] == 'x' || name[2] == 'p')
+ return name[0] == '\0';
+ break;
+ case 'd':
+ if (name[2] == 'i')
+ return name[0] == '\0';
+ break;
+ case 'i':
+ if (name[2] == 'p')
+ return name[0] == '\0';
+ break;
+ case 's':
+ if (name[2] == 'i' || name[2] == 'p')
+ return name[0] == '\0';
+ break;
+ }
+ }
+ }
+ return false;
+}
+
void
ABIMacOSX_i386::Initialize()
{
diff --git a/lldb/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h b/lldb/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h
index 20dbc4af5ec..e50330fda76 100644
--- a/lldb/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h
+++ b/lldb/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h
@@ -17,71 +17,195 @@
#include "lldb/lldb-private.h"
#include "lldb/Target/ABI.h"
#include "lldb/Core/Value.h"
-
-namespace lldb_private {
- class ABIMacOSX_i386 :
+class ABIMacOSX_i386 :
public lldb_private::ABI
+{
+public:
+
+ enum
{
- public:
- ~ABIMacOSX_i386() { }
-
- virtual size_t
- GetRedZoneSize () const;
-
- virtual bool
- PrepareTrivialCall (Thread &thread,
- lldb::addr_t sp,
- lldb::addr_t functionAddress,
- lldb::addr_t returnAddress,
- lldb::addr_t arg,
- lldb::addr_t *this_arg,
- lldb::addr_t *cmd_arg) const;
-
- virtual bool
- PrepareNormalCall (Thread &thread,
- lldb::addr_t sp,
- lldb::addr_t functionAddress,
- lldb::addr_t returnAddress,
- ValueList &args) const;
-
- virtual bool
- GetArgumentValues (Thread &thread,
- ValueList &values) const;
-
- virtual bool
- GetReturnValue (Thread &thread,
- Value &value) const;
-
- //------------------------------------------------------------------
- // Static Functions
- //------------------------------------------------------------------
- static void
- Initialize();
-
- static void
- Terminate();
-
- static lldb_private::ABI *
- CreateInstance (const ArchSpec &arch);
-
- //------------------------------------------------------------------
- // PluginInterface protocol
- //------------------------------------------------------------------
- virtual const char *
- GetPluginName();
-
- virtual const char *
- GetShortPluginName();
-
- virtual uint32_t
- GetPluginVersion();
-
- protected:
- private:
- ABIMacOSX_i386() : lldb_private::ABI() { } // Call CreateInstance instead.
+ gcc_eax = 0,
+ gcc_ecx,
+ gcc_edx,
+ gcc_ebx,
+ gcc_ebp,
+ gcc_esp,
+ gcc_esi,
+ gcc_edi,
+ gcc_eip,
+ gcc_eflags
};
-} // namespace lldb_private
+ enum
+ {
+ dwarf_eax = 0,
+ dwarf_ecx,
+ dwarf_edx,
+ dwarf_ebx,
+ dwarf_esp,
+ dwarf_ebp,
+ dwarf_esi,
+ dwarf_edi,
+ dwarf_eip,
+ dwarf_eflags,
+ dwarf_stmm0 = 11,
+ dwarf_stmm1,
+ dwarf_stmm2,
+ dwarf_stmm3,
+ dwarf_stmm4,
+ dwarf_stmm5,
+ dwarf_stmm6,
+ dwarf_stmm7,
+ dwarf_xmm0 = 21,
+ dwarf_xmm1,
+ dwarf_xmm2,
+ dwarf_xmm3,
+ dwarf_xmm4,
+ dwarf_xmm5,
+ dwarf_xmm6,
+ dwarf_xmm7,
+ dwarf_ymm0 = dwarf_xmm0,
+ dwarf_ymm1 = dwarf_xmm1,
+ dwarf_ymm2 = dwarf_xmm2,
+ dwarf_ymm3 = dwarf_xmm3,
+ dwarf_ymm4 = dwarf_xmm4,
+ dwarf_ymm5 = dwarf_xmm5,
+ dwarf_ymm6 = dwarf_xmm6,
+ dwarf_ymm7 = dwarf_xmm7,
+ };
+
+ enum
+ {
+ gdb_eax = 0,
+ gdb_ecx = 1,
+ gdb_edx = 2,
+ gdb_ebx = 3,
+ gdb_esp = 4,
+ gdb_ebp = 5,
+ gdb_esi = 6,
+ gdb_edi = 7,
+ gdb_eip = 8,
+ gdb_eflags = 9,
+ gdb_cs = 10,
+ gdb_ss = 11,
+ gdb_ds = 12,
+ gdb_es = 13,
+ gdb_fs = 14,
+ gdb_gs = 15,
+ gdb_stmm0 = 16,
+ gdb_stmm1 = 17,
+ gdb_stmm2 = 18,
+ gdb_stmm3 = 19,
+ gdb_stmm4 = 20,
+ gdb_stmm5 = 21,
+ gdb_stmm6 = 22,
+ gdb_stmm7 = 23,
+ gdb_fctrl = 24, gdb_fcw = gdb_fctrl,
+ gdb_fstat = 25, gdb_fsw = gdb_fstat,
+ gdb_ftag = 26, gdb_ftw = gdb_ftag,
+ gdb_fiseg = 27, gdb_fpu_cs = gdb_fiseg,
+ gdb_fioff = 28, gdb_ip = gdb_fioff,
+ gdb_foseg = 29, gdb_fpu_ds = gdb_foseg,
+ gdb_fooff = 30, gdb_dp = gdb_fooff,
+ gdb_fop = 31,
+ gdb_xmm0 = 32,
+ gdb_xmm1 = 33,
+ gdb_xmm2 = 34,
+ gdb_xmm3 = 35,
+ gdb_xmm4 = 36,
+ gdb_xmm5 = 37,
+ gdb_xmm6 = 38,
+ gdb_xmm7 = 39,
+ gdb_mxcsr = 40,
+ gdb_mm0 = 41,
+ gdb_mm1 = 42,
+ gdb_mm2 = 43,
+ gdb_mm3 = 44,
+ gdb_mm4 = 45,
+ gdb_mm5 = 46,
+ gdb_mm6 = 47,
+ gdb_mm7 = 48,
+ gdb_ymm0 = gdb_xmm0,
+ gdb_ymm1 = gdb_xmm1,
+ gdb_ymm2 = gdb_xmm2,
+ gdb_ymm3 = gdb_xmm3,
+ gdb_ymm4 = gdb_xmm4,
+ gdb_ymm5 = gdb_xmm5,
+ gdb_ymm6 = gdb_xmm6,
+ gdb_ymm7 = gdb_xmm7
+ };
+
+ ~ABIMacOSX_i386() { }
+
+ virtual size_t
+ GetRedZoneSize () const;
+
+ virtual bool
+ PrepareTrivialCall (lldb_private::Thread &thread,
+ lldb::addr_t sp,
+ lldb::addr_t functionAddress,
+ lldb::addr_t returnAddress,
+ lldb::addr_t arg,
+ lldb::addr_t *this_arg,
+ lldb::addr_t *cmd_arg) const;
+
+ virtual bool
+ PrepareNormalCall (lldb_private::Thread &thread,
+ lldb::addr_t sp,
+ lldb::addr_t functionAddress,
+ lldb::addr_t returnAddress,
+ lldb_private::ValueList &args) const;
+
+ virtual bool
+ GetArgumentValues (lldb_private::Thread &thread,
+ lldb_private::ValueList &values) const;
+
+ virtual bool
+ GetReturnValue (lldb_private::Thread &thread,
+ lldb_private::Value &value) const;
+
+ virtual bool
+ CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan);
+
+ virtual bool
+ CreateDefaultUnwindPlan (lldb_private::UnwindPlan &unwind_plan);
+
+ virtual bool
+ RegisterIsVolatile (const lldb_private::RegisterInfo *reg_info);
+
+
+ //------------------------------------------------------------------
+ // Static Functions
+ //------------------------------------------------------------------
+ static void
+ Initialize();
+
+ static void
+ Terminate();
+
+ static lldb::ABISP
+ CreateInstance (const lldb_private::ArchSpec &arch);
+
+ //------------------------------------------------------------------
+ // PluginInterface protocol
+ //------------------------------------------------------------------
+ virtual const char *
+ GetPluginName();
+
+ virtual const char *
+ GetShortPluginName();
+
+ virtual uint32_t
+ GetPluginVersion();
+
+protected:
+ bool
+ RegisterIsCalleeSaved (const lldb_private::RegisterInfo *reg_info);
+
+private:
+ ABIMacOSX_i386() : lldb_private::ABI() { } // Call CreateInstance instead.
+};
+
#endif // liblldb_ABI_h_
diff --git a/lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp b/lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp
index 5c2cd7403ec..3ee0562b7e8 100644
--- a/lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp
+++ b/lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp
@@ -17,6 +17,7 @@
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Value.h"
#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/UnwindPlan.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
@@ -32,6 +33,8 @@ static const char *pluginName = "ABISysV_x86_64";
static const char *pluginDesc = "System V ABI for x86_64 targets";
static const char *pluginShort = "abi.sysv-x86_64";
+
+
size_t
ABISysV_x86_64::GetRedZoneSize () const
{
@@ -41,12 +44,17 @@ ABISysV_x86_64::GetRedZoneSize () const
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
-lldb_private::ABI *
+ABISP
ABISysV_x86_64::CreateInstance (const ArchSpec &arch)
{
+ static ABISP g_abi_sp;
if (arch.GetTriple().getArch() == llvm::Triple::x86_64)
- return new ABISysV_x86_64;
- return NULL;
+ {
+ if (!g_abi_sp)
+ g_abi_sp.reset (new ABISysV_x86_64);
+ return g_abi_sp;
+ }
+ return ABISP();
}
bool
@@ -446,6 +454,143 @@ ABISysV_x86_64::GetReturnValue (Thread &thread,
return true;
}
+bool
+ABISysV_x86_64::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)
+{
+ uint32_t reg_kind = unwind_plan.GetRegisterKind();
+ uint32_t sp_reg_num = LLDB_INVALID_REGNUM;
+ uint32_t pc_reg_num = LLDB_INVALID_REGNUM;
+
+ switch (reg_kind)
+ {
+ case eRegisterKindDWARF:
+ case eRegisterKindGCC:
+ sp_reg_num = gcc_dwarf_rsp;
+ pc_reg_num = gcc_dwarf_rip;
+ break;
+
+ case eRegisterKindGDB:
+ sp_reg_num = gdb_rsp;
+ pc_reg_num = gdb_rip;
+ break;
+
+ case eRegisterKindGeneric:
+ sp_reg_num = LLDB_REGNUM_GENERIC_SP;
+ pc_reg_num = LLDB_REGNUM_GENERIC_PC;
+ break;
+ }
+
+ if (sp_reg_num == LLDB_INVALID_REGNUM ||
+ pc_reg_num == LLDB_INVALID_REGNUM)
+ return false;
+
+ UnwindPlan::Row row;
+ row.SetCFARegister (sp_reg_num);
+ row.SetCFAOffset (8);
+ row.SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, -8, false);
+ unwind_plan.AppendRow (row);
+ unwind_plan.SetSourceName (pluginName);
+ return true;
+}
+
+bool
+ABISysV_x86_64::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)
+{
+ uint32_t reg_kind = unwind_plan.GetRegisterKind();
+ uint32_t fp_reg_num = LLDB_INVALID_REGNUM;
+ uint32_t sp_reg_num = LLDB_INVALID_REGNUM;
+ uint32_t pc_reg_num = LLDB_INVALID_REGNUM;
+
+ switch (reg_kind)
+ {
+ case eRegisterKindDWARF:
+ case eRegisterKindGCC:
+ fp_reg_num = gcc_dwarf_rbp;
+ sp_reg_num = gcc_dwarf_rsp;
+ pc_reg_num = gcc_dwarf_rip;
+ break;
+
+ case eRegisterKindGDB:
+ fp_reg_num = gdb_rbp;
+ sp_reg_num = gdb_rsp;
+ pc_reg_num = gdb_rip;
+ break;
+
+ case eRegisterKindGeneric:
+ fp_reg_num = LLDB_REGNUM_GENERIC_FP;
+ sp_reg_num = LLDB_REGNUM_GENERIC_SP;
+ pc_reg_num = LLDB_REGNUM_GENERIC_PC;
+ break;
+ }
+
+ if (fp_reg_num == LLDB_INVALID_REGNUM ||
+ sp_reg_num == LLDB_INVALID_REGNUM ||
+ pc_reg_num == LLDB_INVALID_REGNUM)
+ return false;
+
+ UnwindPlan::Row row;
+
+ const int32_t ptr_size = 8;
+ row.SetCFARegister (LLDB_REGNUM_GENERIC_FP);
+ row.SetCFAOffset (2 * ptr_size);
+ row.SetOffset (0);
+
+ row.SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true);
+ row.SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true);
+ row.SetRegisterLocationToAtCFAPlusOffset(sp_reg_num, ptr_size * 0, true);
+
+ unwind_plan.AppendRow (row);
+ unwind_plan.SetSourceName ("x86_64 default unwind plan");
+ return true;
+}
+
+bool
+ABISysV_x86_64::RegisterIsVolatile (const RegisterInfo *reg_info)
+{
+ return !RegisterIsCalleeSaved (reg_info);
+}
+
+bool
+ABISysV_x86_64::RegisterIsCalleeSaved (const RegisterInfo *reg_info)
+{
+ if (reg_info)
+ {
+ // Volatile registers include: rbx, rbp, rsp, r12, r13, r14, r15, rip
+ const char *name = reg_info->name;
+ if (name[0] == 'r')
+ {
+ switch (name[1])
+ {
+ case '1': // r12, r13, r14, r15
+ if (name[2] >= '2' && name[2] <= '5')
+ return name[3] == '\0';
+ break;
+
+ case 'b': // rbp, rbx
+ if (name[2] == 'p' || name[2] == 'x')
+ return name[3] == '\0';
+ break;
+
+ case 'i': // rip
+ if (name[2] == 'p')
+ return name[3] == '\0';
+ break;
+
+ case 's': // rsp
+ if (name[2] == 'p')
+ return name[3] == '\0';
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+ return false;
+}
+
+
+
void
ABISysV_x86_64::Initialize()
{
diff --git a/lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h b/lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h
index beb617891c2..e1ac132da8d 100644
--- a/lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h
+++ b/lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h
@@ -17,19 +17,158 @@
#include "lldb/lldb-private.h"
#include "lldb/Target/ABI.h"
-namespace lldb_private {
-
class ABISysV_x86_64 :
public lldb_private::ABI
{
public:
- ~ABISysV_x86_64() { }
+
+ enum gcc_dwarf_regnums
+ {
+ gcc_dwarf_rax = 0,
+ gcc_dwarf_rdx,
+ gcc_dwarf_rcx,
+ gcc_dwarf_rbx,
+ gcc_dwarf_rsi,
+ gcc_dwarf_rdi,
+ gcc_dwarf_rbp,
+ gcc_dwarf_rsp,
+ gcc_dwarf_r8,
+ gcc_dwarf_r9,
+ gcc_dwarf_r10,
+ gcc_dwarf_r11,
+ gcc_dwarf_r12,
+ gcc_dwarf_r13,
+ gcc_dwarf_r14,
+ gcc_dwarf_r15,
+ gcc_dwarf_rip,
+ gcc_dwarf_xmm0,
+ gcc_dwarf_xmm1,
+ gcc_dwarf_xmm2,
+ gcc_dwarf_xmm3,
+ gcc_dwarf_xmm4,
+ gcc_dwarf_xmm5,
+ gcc_dwarf_xmm6,
+ gcc_dwarf_xmm7,
+ gcc_dwarf_xmm8,
+ gcc_dwarf_xmm9,
+ gcc_dwarf_xmm10,
+ gcc_dwarf_xmm11,
+ gcc_dwarf_xmm12,
+ gcc_dwarf_xmm13,
+ gcc_dwarf_xmm14,
+ gcc_dwarf_xmm15,
+ gcc_dwarf_stmm0,
+ gcc_dwarf_stmm1,
+ gcc_dwarf_stmm2,
+ gcc_dwarf_stmm3,
+ gcc_dwarf_stmm4,
+ gcc_dwarf_stmm5,
+ gcc_dwarf_stmm6,
+ gcc_dwarf_stmm7,
+ gcc_dwarf_ymm0 = gcc_dwarf_xmm0,
+ gcc_dwarf_ymm1 = gcc_dwarf_xmm1,
+ gcc_dwarf_ymm2 = gcc_dwarf_xmm2,
+ gcc_dwarf_ymm3 = gcc_dwarf_xmm3,
+ gcc_dwarf_ymm4 = gcc_dwarf_xmm4,
+ gcc_dwarf_ymm5 = gcc_dwarf_xmm5,
+ gcc_dwarf_ymm6 = gcc_dwarf_xmm6,
+ gcc_dwarf_ymm7 = gcc_dwarf_xmm7,
+ gcc_dwarf_ymm8 = gcc_dwarf_xmm8,
+ gcc_dwarf_ymm9 = gcc_dwarf_xmm9,
+ gcc_dwarf_ymm10 = gcc_dwarf_xmm10,
+ gcc_dwarf_ymm11 = gcc_dwarf_xmm11,
+ gcc_dwarf_ymm12 = gcc_dwarf_xmm12,
+ gcc_dwarf_ymm13 = gcc_dwarf_xmm13,
+ gcc_dwarf_ymm14 = gcc_dwarf_xmm14,
+ gcc_dwarf_ymm15 = gcc_dwarf_xmm15
+ };
+
+ enum gdb_regnums
+ {
+ gdb_rax = 0,
+ gdb_rbx = 1,
+ gdb_rcx = 2,
+ gdb_rdx = 3,
+ gdb_rsi = 4,
+ gdb_rdi = 5,
+ gdb_rbp = 6,
+ gdb_rsp = 7,
+ gdb_r8 = 8,
+ gdb_r9 = 9,
+ gdb_r10 = 10,
+ gdb_r11 = 11,
+ gdb_r12 = 12,
+ gdb_r13 = 13,
+ gdb_r14 = 14,
+ gdb_r15 = 15,
+ gdb_rip = 16,
+ gdb_rflags = 17,
+ gdb_cs = 18,
+ gdb_ss = 19,
+ gdb_ds = 20,
+ gdb_es = 21,
+ gdb_fs = 22,
+ gdb_gs = 23,
+ gdb_stmm0 = 24,
+ gdb_stmm1 = 25,
+ gdb_stmm2 = 26,
+ gdb_stmm3 = 27,
+ gdb_stmm4 = 28,
+ gdb_stmm5 = 29,
+ gdb_stmm6 = 30,
+ gdb_stmm7 = 31,
+ gdb_fctrl = 32, gdb_fcw = gdb_fctrl,
+ gdb_fstat = 33, gdb_fsw = gdb_fstat,
+ gdb_ftag = 34, gdb_ftw = gdb_ftag,
+ gdb_fiseg = 35, gdb_fpu_cs = gdb_fiseg,
+ gdb_fioff = 36, gdb_ip = gdb_fioff,
+ gdb_foseg = 37, gdb_fpu_ds = gdb_foseg,
+ gdb_fooff = 38, gdb_dp = gdb_fooff,
+ gdb_fop = 39,
+ gdb_xmm0 = 40,
+ gdb_xmm1 = 41,
+ gdb_xmm2 = 42,
+ gdb_xmm3 = 43,
+ gdb_xmm4 = 44,
+ gdb_xmm5 = 45,
+ gdb_xmm6 = 46,
+ gdb_xmm7 = 47,
+ gdb_xmm8 = 48,
+ gdb_xmm9 = 49,
+ gdb_xmm10 = 50,
+ gdb_xmm11 = 51,
+ gdb_xmm12 = 52,
+ gdb_xmm13 = 53,
+ gdb_xmm14 = 54,
+ gdb_xmm15 = 55,
+ gdb_mxcsr = 56,
+ gdb_ymm0 = gdb_xmm0,
+ gdb_ymm1 = gdb_xmm1,
+ gdb_ymm2 = gdb_xmm2,
+ gdb_ymm3 = gdb_xmm3,
+ gdb_ymm4 = gdb_xmm4,
+ gdb_ymm5 = gdb_xmm5,
+ gdb_ymm6 = gdb_xmm6,
+ gdb_ymm7 = gdb_xmm7,
+ gdb_ymm8 = gdb_xmm8,
+ gdb_ymm9 = gdb_xmm9,
+ gdb_ymm10 = gdb_xmm10,
+ gdb_ymm11 = gdb_xmm11,
+ gdb_ymm12 = gdb_xmm12,
+ gdb_ymm13 = gdb_xmm13,
+ gdb_ymm14 = gdb_xmm14,
+ gdb_ymm15 = gdb_xmm15
+ };
+
+ ~ABISysV_x86_64()
+ {
+ }
virtual size_t
GetRedZoneSize () const;
virtual bool
- PrepareTrivialCall (Thread &thread,
+ PrepareTrivialCall (lldb_private::Thread &thread,
lldb::addr_t sp,
lldb::addr_t functionAddress,
lldb::addr_t returnAddress,
@@ -38,19 +177,28 @@ public:
lldb::addr_t *cmd_arg) const;
virtual bool
- PrepareNormalCall (Thread &thread,
+ PrepareNormalCall (lldb_private::Thread &thread,
lldb::addr_t sp,
lldb::addr_t functionAddress,
lldb::addr_t returnAddress,
- ValueList &args) const;
+ lldb_private::ValueList &args) const;
+
+ virtual bool
+ GetArgumentValues (lldb_private::Thread &thread,
+ lldb_private::ValueList &values) const;
virtual bool
- GetArgumentValues (Thread &thread,
- ValueList &values) const;
+ GetReturnValue (lldb_private::Thread &thread,
+ lldb_private::Value &value) const;
virtual bool
- GetReturnValue (Thread &thread,
- Value &value) const;
+ CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan);
+
+ virtual bool
+ CreateDefaultUnwindPlan (lldb_private::UnwindPlan &unwind_plan);
+
+ virtual bool
+ RegisterIsVolatile (const lldb_private::RegisterInfo *reg_info);
//------------------------------------------------------------------
// Static Functions
@@ -61,8 +209,8 @@ public:
static void
Terminate();
- static lldb_private::ABI *
- CreateInstance (const ArchSpec &arch);
+ static lldb::ABISP
+ CreateInstance (const lldb_private::ArchSpec &arch);
//------------------------------------------------------------------
// PluginInterface protocol
@@ -77,10 +225,12 @@ public:
GetPluginVersion();
protected:
+
+ bool
+ RegisterIsCalleeSaved (const lldb_private::RegisterInfo *reg_info);
+
private:
ABISysV_x86_64() : lldb_private::ABI() { } // Call CreateInstance instead.
};
-} // namespace lldb_private
-
#endif // liblldb_ABI_h_
OpenPOWER on IntegriCloud